Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error messages for JWT verification errors #3600

Open
wolfgangwalther opened this issue Jun 17, 2024 · 1 comment
Open

Improve error messages for JWT verification errors #3600

wolfgangwalther opened this issue Jun 17, 2024 · 1 comment
Labels
difficulty: beginner Pure Haskell task hygiene cleanup or refactoring messages user-facing error/informative messages

Comments

@wolfgangwalther
Copy link
Member

In #3598 I added a new IO test showing how many JWT errors we currently expose by just showing internal errors via show. Those are not very user friendly:

with run(env=env) as postgrest:
headers = jwtauthheader({}, "other secret")
response = postgrest.session.get("/", headers=headers)
assert response.status_code == 401
assert response.json()["message"] == "JWSError JWSInvalidSignature"
headers = jwtauthheader({"role": "not_existing"}, SECRET)
response = postgrest.session.get("/", headers=headers)
# TODO: Should this return 401?
assert response.status_code == 400
assert response.json()["message"] == 'role "not_existing" does not exist'
# -31 seconds, because we allow clock skew of 30 seconds
headers = jwtauthheader({"exp": relativeSeconds(-31)}, SECRET)
response = postgrest.session.get("/", headers=headers)
assert response.status_code == 401
assert response.json()["message"] == "JWT expired"
# 31 seconds, because we allow clock skew of 30 seconds
headers = jwtauthheader({"nbf": relativeSeconds(31)}, SECRET)
response = postgrest.session.get("/", headers=headers)
assert response.status_code == 401
assert response.json()["message"] == "JWTNotYetValid"
# 31 seconds, because we allow clock skew of 30 seconds
headers = jwtauthheader({"iat": relativeSeconds(31)}, SECRET)
response = postgrest.session.get("/", headers=headers)
assert response.status_code == 401
assert response.json()["message"] == "JWTIssuedAtFuture"
headers = jwtauthheader({"aud": "not set"}, SECRET)
response = postgrest.session.get("/", headers=headers)
assert response.status_code == 401
assert response.json()["message"] == "JWTNotInAudience"
# partial token, no signature
headers = authheader("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.bm90IGFuIG9iamVjdA")
response = postgrest.session.get("/", headers=headers)
assert response.status_code == 401
assert (
response.json()["message"]
== "JWSError (CompactDecodeError Invalid number of parts: Expected 3 parts; got 2)"
)
# token with algorithm "none"
headers = authheader(
"eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.e30.yOBhlOIqn56T-4NvyEXCjfi3UmyQZ-BzXtePMO2NgRI"
)
response = postgrest.session.get("/", headers=headers)
assert response.status_code == 401
assert response.json()["message"] == "JWSError JWSNoSignatures"

For at least a few of them we should improve the error message and maybe differentiate them in https://postgrest.org/en/v12/references/errors.html#group-3-jwt? I.e. give them our own PGRST error code.

@wolfgangwalther wolfgangwalther added difficulty: beginner Pure Haskell task hygiene cleanup or refactoring messages user-facing error/informative messages labels Jun 17, 2024
@laurenceisla
Copy link
Member

Related issue: #1840

I.e. give them our own PGRST error code.

Agree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty: beginner Pure Haskell task hygiene cleanup or refactoring messages user-facing error/informative messages
Development

No branches or pull requests

2 participants