feat(auth): surface debuggable reasons for rejected issuer/session tokens#272
Open
jeroenrinzema wants to merge 1 commit into
Open
feat(auth): surface debuggable reasons for rejected issuer/session tokens#272jeroenrinzema wants to merge 1 commit into
jeroenrinzema wants to merge 1 commit into
Conversation
…kens External JWT failures (trusted issuer and Lunogram sessions) all collapsed into a single bare "unauthorized", so an integrator could not tell a malformed token (e.g. a missing `exp` claim) from a wrong signing key. Surface a precise reason — but only once the token has proven to be authentically ours, so we never leak whether an issuer or project exists: - Trusted issuer: a reason is returned only after the token's `iss` resolves to a configured issuer. Failures before that (empty/unparseable token, unknown issuer) stay a generic ErrUnauthorized. - Session: a reason is returned only after the ES256 signature verifies (golang-jwt validates claims strictly after the signature). Signature, signing-method, and format failures stay ErrUnauthorized so the auth chain still falls through to the trusted-issuer handler. The HTTP status is unchanged (still 401 via SecurityRequirementsError); only the problem detail gains a specific, fixable message such as `token is missing the required "exp" claim` or `token has expired`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When authenticating with a trusted issuer (or a Lunogram session), any token failure collapsed into a single bare
unauthorized. If a token was missing data such as theexpclaim, the caller got the same 401 as a wrong signing key — with no way to tell which, making integrations painful to debug.Change
Surface a precise, fixable reason in the 401 — but only once the token has proven to be authentically ours, so we never leak whether an issuer or project exists.
Trusted issuer (
trusted_issuer.go)issresolves to a configured trusted issuer. Failures before that (empty/unparseable token, unknown issuer) stay a genericErrUnauthorized— they'd otherwise leak issuer/project existence.verifyTrustedIssuerTokennow preserves the underlying golang-jwt cause instead of flattening it, anddescribeTokenErrormaps it to a safe message (missing claim, expired, not-yet-valid, issuer/audience mismatch). Signature / malformed / key-resolution failures collapse to a generic reason so verification internals never leak.Session (
session.go)ErrTokenInvalidClaims) proves the token is one of ours.ErrUnauthorizedso the auth chain still falls through to the trusted-issuer handler (a real trusted-issuer JWT is RS256 and must not be mis-described as a session token).Safety / compatibility
401viaSecurityRequirementsError. Only the problemdetailgains a specific message, e.g.token is missing the required "exp" claimortoken has expired.errors.Is(err, ErrUnauthorized), so the middleware returns them instead of collapsing to a bareunauthorized. This only short-circuits the chain for tokens already proven to belong to that scheme, so no request that currently succeeds can regress.Tests
Updated and extended
trusted_issuer_middleware_test.goandsession_middleware_test.goto cover the new reasons (missingexp, expired, wrong key, wrong/missing issuer, missing/invalidamid, missingsub, unknown session method) and to assert that signature/format failures still stay generic and fall through.