Skip to content

fix(backend): report a rejected token as Unauthenticated, not as a crash - #299

Merged
sabinem merged 1 commit into
mainfrom
fix/jwt-error-codes
Sep 11, 2026
Merged

fix(backend): report a rejected token as Unauthenticated, not as a crash#299
sabinem merged 1 commit into
mainfrom
fix/jwt-error-codes

Conversation

@sabinem

@sabinem sabinem commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Expired logins stop looking like server crashes

Before: your login token expires — completely routine — and the backend reported it as an internal server error. Two consequences. Users got misleading messages: the invitation page had to treat "server error" as "your sign-in expired", because that's what actually arrived, so a genuine server problem told people to sign in again over an invitation that was working fine. And in the logs, every ordinary expired session showed up as a server fault, so anything watching error rates was counting normal behaviour as breakage.

The cause: two versions of the same JWT library were installed. The code that reads tokens used the new one; the code that translated the errors checked for a type the new version had deleted. So the translation never matched, and every rejected token fell through to the catch-all: "internal error".

Now: a rejected token is reported as a rejected token. A real server fault is reported as a real server fault, and the invitation page says so instead of blaming your sign-in.

Details

  • Matches the library's error values the way the new version reports them, and adds the wrong-issuer case that nothing was translating.
  • Removes the old library version entirely — it was only installed to keep the broken code compiling.
  • The existing tests couldn't have caught this: they checked the error text, which comes from the library and matched whether or not the translation ran. They now check the error code, and all five were confirmed failing before the fix.

Two jwt versions were installed: `auth.go` reads tokens with v5, while
`errors.go` matched v4's `*jwt.ValidationError` — a type v5 deleted. The
match never fired, so every expired, malformed, badly signed or wrongly
issued token fell past the Unauthenticated list to `codes.Internal`, and
a routine expired session was reported and logged as a server fault.

Matches v5's sentinels with `errors.Is`, adds the issuer case v5 raises
that nothing was mapping, and drops the now-unused jwt/v4 dependency —
`errors.go` was its only importer. The invitation page no longer has to
read INTERNAL as an expired session, so a real fault can say so.

The auth tests asserted error messages, which come from the library and
matched either way. They now assert the gRPC code, and did fail before
this change.
@sabinem
sabinem merged commit f761aaf into main Sep 11, 2026
3 checks passed
@sabinem
sabinem deleted the fix/jwt-error-codes branch September 11, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant