2HAASStart a project
All posts

Guides

JWT best practices: expiry, storage and validation

JSON Web Tokens are simple to issue and easy to get wrong. Short lifetimes, refresh token rotation, safe storage and strict validation close the common holes.

The 2HAAS team3 min read

A JSON Web Token (JWT) is three Base64 encoded parts separated by dots: a header, a payload and a signature. The server signs the token at login, and afterwards trusts any request that presents a token with a valid signature. No session lookup is needed.

That convenience is also the risk. A stolen token works for the thief exactly as it works for the user, and a server that validates carelessly will accept tokens it should not. These practices cover the common failures.

1. Keep access tokens short-lived

An access token should expire in minutes, typically 5 to 15. If it leaks, the damage has a time limit.

To avoid logging users out every few minutes, issue a longer-lived refresh token as well. When the access token expires, the client exchanges the refresh token for a new one.

Rotate refresh tokens. Each use returns a new refresh token and invalidates the old one. If an old one is ever presented again, someone has copied it, and the server should revoke the whole session.

2. Store tokens where scripts cannot reach them

Client Refresh token Access token
Browser A cookie marked HttpOnly, Secure and SameSite In memory
Mobile app Keychain on iOS, Keystore on Android In memory

Do not keep tokens in localStorage. Any script that runs on your page, including one injected through a vulnerable dependency, can read it.

3. Validate every claim on every request

Checking that the token decodes is not validation. The server must verify:

  • the signature, against an explicit list of allowed algorithms,
  • exp, so expired tokens are rejected,
  • iss, so the token came from your auth server,
  • aud, so a token issued for another service is not accepted here.

Use a maintained library and state those expectations explicitly.

import { jwtVerify } from "jose";

const { payload } = await jwtVerify(token, publicKey, {
  algorithms: ["RS256"],
  issuer: "https://auth.example.com",
  audience: "orders-api",
});

Never let the token's own header decide which algorithm to use, and never accept none.

4. Use strong keys and rotate them

  • For HMAC signing such as HS256, the secret must be long and random: at least 256 bits, generated and not typed.
  • When several services verify tokens, prefer asymmetric signing such as RS256 or ES256. Only the auth server holds the private key. Everyone else verifies with the public key.
  • Publish public keys through a JWKS endpoint and rotate them on a schedule. The kid header tells verifiers which key to use.

5. Plan for revocation

A JWT cannot be recalled once issued. Short expiry is the main defence. For logout and compromised accounts, keep a small denylist of token IDs (jti) until they expire, and revoke the refresh token.

What does not belong in a token

The payload is signed, not encrypted. Anyone holding the token can read it. Keep it to identifiers and roles: no passwords, no personal data, no secrets.

The flow in practice

A user logs in on a mobile app. The auth server returns a ten minute access token and a refresh token, which the app stores in the device's secure storage. API calls carry the access token. When it expires, the app exchanges the refresh token for a new pair, and the user never sees a login screen.

Tokens are one layer. For the rest, see our API endpoint security checklist.

Keep reading

  1. Guides3 min read

    API endpoint security: a practical checklist

    Most API breaches come from a short list of mistakes: missing authorization checks, trusted input and no rate limits. A checklist to review every endpoint against.

  2. Guides3 min read

    Error handling in microservices: retries and circuit breakers

    In a distributed system, something is always failing a little. Timeouts, retries with backoff, circuit breakers and consistent errors keep one fault from spreading.

  3. Guides5 min read

    Enhance Web Security with Content Security Policy

    Learn how to implement a Content Security Policy (CSP) to protect your web applications from common attacks like XSS and data injection.

Tell us what’s in the way.

A few lines is enough. You get a candid yes, a candid no, or a sharper question.

  • Working software in week four
  • A reply in one business day
  • Handover is the deliverable

Prefer email? [email protected]

The problem, who it is for, and what is in the way right now.

One business day to a real reply. No sales sequence, no call required.