How to Secure an API with JWT Authentication
Issue short-lived RS256 JWT access tokens, validate them as bearer credentials with strict issuer and audience checks, add a rotating refresh token flow, and rotate signing keys via JWKS.
What and why
A JSON Web Token (JWT) is a signed, self-contained token carrying claims about a user. APIs use short-lived JWT access tokens so each request can be authenticated without a database lookup. Done right, JWTs are stateless and scalable; done wrong, they are a common source of vulnerabilities.
Prerequisites
- A REST API you control.
- A user store to validate credentials.
- Understanding of the
Authorizationheader.
Steps
1. Choose a signing algorithm
Prefer asymmetric RS256 or ES256 so verifiers only need the public key. Never accept the none algorithm, and never let the token header dictate the algorithm during verification.
2. Issue an access token on login
After verifying credentials, sign a token with short expiry:
const { SignJWT } = require('jose');
const token = await new SignJWT({ role: user.role })
.setProtectedHeader({ alg: 'RS256', kid })
.setSubject(user.id)
.setIssuer('https://api.example.com')
.setAudience('example-clients')
.setExpirationTime('15m')
.sign(privateKey);
3. Validate the bearer token
On each request, read Authorization: Bearer <token> and verify it:
const { payload } = await jwtVerify(token, publicKey, {
issuer: 'https://api.example.com', audience: 'example-clients',
});
req.user = { id: payload.sub, role: payload.role };
Reject expired tokens and tokens whose iss or aud do not match.
4. Add a refresh token flow
Access tokens are short-lived. Issue a long-lived refresh token, store it server-side (so it can be revoked), and exchange it for a new access token. Rotate the refresh token on each use and detect reuse of an old one as a theft signal.
5. Rotate signing keys
Publish keys at a JWKS endpoint and include a kid in each token header so verifiers select the right key. To rotate, add a new key, sign with it, keep the old key for verification until all old tokens expire, then remove it.
Verification
- A valid token grants access; a tampered token is rejected.
- An expired token returns 401.
- After rotation, tokens signed by the new key validate against the JWKS.
Next Steps
Keep access tokens short (5-15 minutes), store tokens in HttpOnly cookies for browsers, scope tokens to least privilege, and add a revocation list or token versioning for emergency invalidation.
Prerequisites
- A REST API
- Understanding of HTTP headers
- A user store for credentials
Steps
- 1Choose a signing algorithm
- 2Issue an access token on login
- 3Validate the bearer token
- 4Add a refresh token flow
- 5Rotate signing keys