Tessera

← All technologies

TECHNOLOGY

JSON Web Tokens (JWT)

JSON Web Tokens (JWT)

One key, one algorithm, an explicit allow-list, and token key-URLs ignored — defeating alg-confusion and SSRF.

A JWT is only as safe as its verifier. Tessera follows the JWT BCP (RFC 8725) literally: an explicit algorithm allow-list, alg:none rejected, and one key bound to one algorithm so an attacker cannot downgrade an RS256 public key into an HS256 shared secret. Every token must carry an explicit typ and pass iss/aud/exp checks, which is what stops an ID token being replayed as an access token (RFC 9068).

Keys are never selected by the token: jku, x5u and inline jwk headers are ignored, and verification keys come only from a cached, allow-listed JWKS. The engine validates self-contained access tokens locally at the edge and reaches for introspection (RFC 7662) only when it needs real-time revocation of an opaque token.

Code

rust
// Pin the algorithm allow-list; never trust the token's own `alg`.
// One key bound to one algorithm defeats the RS256 to HS256 confusion attack.
use jsonwebtoken::{decode, Validation, Algorithm, DecodingKey};

let mut v = Validation::new(Algorithm::EdDSA); // internal tokens = EdDSA
v.algorithms = vec![Algorithm::EdDSA];          // explicit allow-list, no `none`
v.required_spec_claims = ["iss", "aud", "exp"].into_iter().map(String::from).collect();
v.set_audience(&[expected_aud]);
v.set_issuer(&[expected_iss]);
// typ must be `at+jwt` for access tokens (RFC 9068); jku/x5u/jwk in the
// token header are IGNORED — keys come only from our cached, allow-listed JWKS.
let data = decode::<Claims>(token, &DecodingKey::from_ed_components(/* ... */), &v)?;

Standards it follows

JSON Web Token Best Current PracticesRFC 8725/BCP 225
https://www.rfc-editor.org/rfc/rfc8725
JSON Web Key (JWK)RFC 7517
https://www.rfc-editor.org/rfc/rfc7517
JWT Profile for OAuth 2.0 Access TokensRFC 9068
https://www.rfc-editor.org/rfc/rfc9068
Token IntrospectionRFC 7662
https://www.rfc-editor.org/rfc/rfc7662

Best practices applied

  • Verify against an explicit algorithm allow-list and reject `alg:none`. source
  • Bind one key to exactly one algorithm to defeat RS256 to HS256 key-confusion. source
  • Require an explicit `typ` (e.g. `at+jwt`) and validate `iss`/`aud`/`exp` so an ID token can't be replayed as an access token. source
  • Ignore token-supplied `jku`/`x5u`/`jwk` — keys come only from the cached, allow-listed JWKS (SSRF defense). source
  • Validate self-contained access tokens locally with cached JWKS; use introspection (RFC 7662) only for opaque / real-time revocation. source