JSON Web Token definition
A JWT (JSON Web Token) is a compact, URL-safe token that carries a set of claims, such as a user ID, roles and an expiry time, signed so the receiver can verify it was issued by a trusted party and not altered. JWTs are widely used as access tokens in OAuth 2.0, OpenID Connect and API authentication.
JWT structure: header, payload and signature
A JWT is three Base64URL-encoded parts joined by dots: header.payload.signature. The header names the signing algorithm, such as RS256 or HS256. The payload holds claims: registered ones such as iss (issuer), sub (subject), aud (audience), exp (expiry) and iat (issued at), plus custom claims like roles or a tenant ID. The signature is computed over the header and payload with a secret or private key.
Encoding is not encryption. Anyone holding a JWT can read its payload, so never put passwords, card numbers or other secrets in it. You can see this for yourself by pasting a token into our JWT decoder, which shows the header and claims instantly. When the contents must be hidden, JWE (JSON Web Encryption) is the encrypted variant.
How JWT authentication works
After a user signs in, an authorization server issues a short-lived access token as a JWT, often with a longer-lived refresh token. The client sends the access token in the Authorization header with each request. The API verifies the signature with the issuer's public key, checks expiry, issuer and audience, then trusts the claims without a database lookup. That statelessness is why JWTs suit microservices and APIs spread across many servers.
This is the pattern behind OAuth 2.0 access tokens and OpenID Connect ID tokens issued by identity providers such as Auth0, Okta, Microsoft Entra ID, Amazon Cognito and Firebase Authentication. Public keys are usually published at a JWKS endpoint, so APIs can fetch and rotate them automatically.
JWT vs session cookies
With server-side sessions, the browser holds a random session ID and the server looks up the session on every request; revoking access is as simple as deleting the session. With JWTs, the token itself carries the data, so servers need no shared session store, but a stolen token stays valid until it expires. Many web apps are simpler and safer with classic sessions, while JWTs shine for APIs, mobile apps and single sign-on across services.
A common hybrid keeps the browser on a secure HttpOnly session cookie while the backend exchanges it for short-lived JWTs when calling internal services, so the browser never handles bearer tokens directly. This backend-for-frontend pattern combines easy revocation for users with stateless checks between services.
Common JWT security mistakes
JWT libraries are mature, but implementations still go wrong in predictable ways, and the same mistakes appear again and again in penetration test reports and security reviews of web and mobile apps. Checking for each one takes minutes:
- Accepting the none algorithm or letting the token choose its algorithm; pin the expected algorithm on the server
- Skipping audience and issuer checks, so a token issued for one service works on another
- Long expiry times with no way to revoke; keep access tokens short-lived and rotate refresh tokens
- Weak HS256 secrets that attackers can brute-force offline
- Storing tokens in localStorage, where any cross-site scripting bug can steal them; prefer HttpOnly cookies in browsers
- Putting sensitive personal data in the readable payload