Definition
JWT / JWS / JWE form a family of IETF standards (RFC 7515 to 7519, 2015) that define a compact, URL-safe and portable format for carrying signed and/or encrypted claims (assertions) in JSON.
It is the fundamental building block of modern authentication (OAuth access tokens, OIDC ID Tokens), application-level signing and the secure transport of structured data (signed webhooks, attestations).
| Standard | RFC | Role |
|---|---|---|
| JWT | 7519 | General format (encoded JSON claims) |
| JWS | 7515 | Signature (integrity, authenticity) |
| JWE | 7516 | Encryption (confidentiality) |
| JWA | 7518 | Algorithms (HS256, RS256, A256GCM…) |
| JWK | 7517 | Representation of keys in JSON |
JWT format (signed = JWS)
Three parts separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNzE0MDAwMDAwfQ
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c- Header (base64url):
{"alg":"HS256","typ":"JWT"} - Payload (base64url):
{"sub":"1234567890","name":"Alice","iat":1714000000} - Signature: HMAC or RSA/ECDSA depending on
alg
The standard claims: iss (issuer), sub (subject), aud (audience), exp (expiration), nbf (not before), iat (issued at), jti (unique anti-replay identifier), plus private claims (email, roles, scope).
Signature algorithms (JWS)
| Algo | Type | Typical use |
|---|---|---|
HS256 | Symmetric HMAC | Tests, monoliths |
RS256 | Asymmetric RSA | Classic OAuth, OIDC |
PS256 | RSA-PSS | Recommended for FAPI (Open Banking) |
ES256 | ECDSA P-256 | Recommended for FAPI, mobile |
EdDSA | Ed25519 | Modern, fast |
none | No signature | Forbidden (historical flaw) |
Best practices: prefer asymmetric (a shareable public key) for public APIs, favor PS256/ES256, never accept alg: none, and always verify the expected alg on the server side rather than trusting the header.
JWE (encryption)
JWE encrypts the payload (confidentiality) in addition to integrity, in 5 parts: header.encrypted_key.iv.ciphertext.tag. Common key encryption: RSA-OAEP, ECDH-ES, A256KW; content encryption: A256GCM, A128CBC-HS256. Use: transporting secret data (tokenized card, KYC data) between services.
JWT vs a traditional session
| Aspect | Session cookie | JWT |
|---|---|---|
| State | Server | Client (stateless) |
| Scaling | Sticky session or shared DB | Trivial |
| Revocation | Server-side deletion | Hard (blacklist) |
| Readability | Opaque | Readable (base64url) |
| Theft risk | httpOnly cookie | Bearer = holder |
Use cases
- OAuth / OIDC: access token (often a JWT; FAPI requires a bound signed JWT), ID Token (always a signed JWT), JAR Request Object (a signed JWT).
- API: a bearer JWT in
Authorization, verified via the public key (JWKS endpoint). - Webhooks: Stripe, GitHub and Slack sign in JWS.
- Identity / KYC: W3C Verifiable Credentials, and SD-JWT (selective disclosure) for the EUDI Wallet.
- eIDAS: JAdES, a qualified signature profile based on JWS.
Known attacks
alg: none: some old libraries accepted an unverified payload.- Algorithm confusion (HS256 vs RS256): signing with the RSA public key as an HMAC secret, if the server does not pin the
alg. kidinjection: a poorly validatedkidcan open up SQL injection or path traversal.- Replay: a stolen JWT stays valid until
exp(mitigation:jti+ cache, short tokens). - Info leak: the payload is readable — put no sensitive data in it, encrypt with JWE if needed.
Best practices
Prefer PS256/ES256, short tokens (5-15 min, long refresh), client-bound tokens (mTLS, DPoP) in FAPI; systematically verify iss, aud, exp, nbf and alg; rotate keys (JWKS); avoid clear-text PII (JWE if necessary); and regularly audit dependencies (CVE).
What JWT / JWS / JWE is not
- Not transport encryption: it is application-level, TLS remains required.
- Not a session: a token, generally short and stateless.
- Not a password: an access token issued after authentication.
- Not natively revocable: valid until expiration, unless a maintained blacklist.
In the PSD2 / Open Finance ecosystem
JWT and JWS are everywhere: OAuth access tokens in PSD2, OIDC ID Tokens (FranceConnect, EUDI Wallet), JAR Request Objects in FAPI, signed webhooks (Bridge, Tink, Plaid) and EUDI Verifiable Credentials in SD-JWT.
Concrete examples
- Stripe webhooks: signed with HMAC SHA-256, a format close to JWS.
- Auth0, Okta, Cognito: issue JWTs.
- OBIE UK: access tokens and ID Tokens in PS256 JWT.
- EUDI Wallet: credentials in SD-JWT (proving "of age" without revealing the date of birth).
- FranceConnect: JWT ID Tokens.
- 2018 vulnerability: the "algorithm confusion" flaw fixed globally in the libraries.
- Tools: jwt.io (debugger),
jose(JS), PyJWT, java-jwt, jose4j.