Description:
The careers-app FastAPI backend has two defects in its JWKS (JSON Web Key Set) handling in apps/careers-app/backend/auth.py, affecting how incoming Asgardeo JWTs are validated:
-
JWKS cache is never invalidated. _get_jwks fetches the key set once into a module-global _jwks_cache and only refetches when it is None. When Asgardeo rotates its signing keys, the cached set goes stale, jwt.decode fails for every newly-issued token, and the service silently degrades to the token-introspection endpoint on every request (introspection results are not cached either), a latent availability/latency cliff that only manifests at key-rotation time.
-
Unsafe keys[0] fallback. When no JWK matches the token's kid, _get_key_for_token falls back to constructing the first key in the set. Verifying a token against an arbitrary key is a correctness/security smell; a kid miss should trigger a JWKS refresh and otherwise be rejected.
Sugged Labels:
bug, careers-app, security
Suggested Assignees:
Affected Product Version:
careers-app latest version
OS, DB, other environment details and versions:
Python 3.12, Asgardeo
Steps to reproduce:
- Start the careers backend and authenticate with a valid Asgardeo JWT (key is cached).
- Simulate Asgardeo key rotation by seeding
_jwks_cache with a stale key set that lacks the token's kid.
- Send a request with a token whose
kid is only in the current JWKS. kid is not found; the code tries to verify against the wrong keys[0] or fails jwt.decode, and every request silently falls back to introspection. The stale cache is never refreshed.
Description:
The careers-app FastAPI backend has two defects in its JWKS (JSON Web Key Set) handling in
apps/careers-app/backend/auth.py, affecting how incoming Asgardeo JWTs are validated:JWKS cache is never invalidated.
_get_jwksfetches the key set once into a module-global_jwks_cacheand only refetches when it isNone. When Asgardeo rotates its signing keys, the cached set goes stale,jwt.decodefails for every newly-issued token, and the service silently degrades to the token-introspection endpoint on every request (introspection results are not cached either), a latent availability/latency cliff that only manifests at key-rotation time.Unsafe
keys[0]fallback. When no JWK matches the token'skid,_get_key_for_tokenfalls back to constructing the first key in the set. Verifying a token against an arbitrary key is a correctness/security smell; akidmiss should trigger a JWKS refresh and otherwise be rejected.Sugged Labels:
bug, careers-app, security
Suggested Assignees:
Affected Product Version:
careers-app latest version
OS, DB, other environment details and versions:
Python 3.12, Asgardeo
Steps to reproduce:
_jwks_cachewith a stale key set that lacks the token'skid.kidis only in the current JWKS.kidis not found; the code tries to verify against the wrongkeys[0]or failsjwt.decode, and every request silently falls back to introspection. The stale cache is never refreshed.