Handle encrypted and HS256 id_tokens in the OIDC callback

Authlib's parse_id_token only reads a 3-segment JWS, so sign-in 500s
against providers that encrypt the id_token (Authentik with an
Encryption Key issues a 5-segment RSA-OAEP-256/A256CBC-HS512 JWE) or
that sign it with the client secret (Authentik with no Signing Key
issues HS256, which the RS256-only JWKS rejects).

OIDCClient subclasses the starlette OAuth2 client and, when the
standard parse fails on a format problem, falls back to an HS256
decode with the client secret, then to the issuer's
userinfo_endpoint. Claim-level failures (bad nonce, expiry, audience,
issuer) are raised as OAuthError so /auth/callback redirects to
/auth/login?error=... instead of blowing up. /auth/authorize likewise
catches provider/network errors and redirects to the login page.
This commit is contained in:
Archibold committed 2026-11-05 16:24:22 +11:00
1 parent 3187b8cf05
commit 27677215bd
3 files changed
+151 -7

No files matched your search

+8
View File
@@ -84,6 +84,14 @@ Flow: `/` with no session redirects to `/auth/login` → `Sign in` →
against the issuer's JWKS → a signed `session` cookie (`HttpOnly`, `SameSite=lax`,
`max_age=UWUDASH_SESSION_TTL`) holds the user id → `/`.
`/auth/callback` also copes with providers whose `id_token` authlib cannot read:
an **encrypted** one (a 5-segment JWE, e.g. an Authentik provider with an
Encryption Key) is resolved through the issuer's `userinfo_endpoint`, and an
**HS256** one (what Authentik issues when no Signing Key is configured) is
verified with the client secret. Claims that fail validation - wrong `iss`,
`aud`, `exp` or `nonce` - are rejected outright: the login redirects to
`/auth/login?error=...` instead of returning a 500.
Once auth is on, every route except `/health`, `/auth/*`, `/static` and FastAPI's
own `/docs` / `/openapi.json` requires a session: unauthenticated requests get
`401` (API) or a redirect to `/auth/login` (the HTML page).