typescriptadvanced

JWT Refresh Token Rotation

Implement secure token rotation with short-lived access tokens and one-time-use refresh tokens.

typescript
import jwt from 'jsonwebtoken';
import crypto from 'crypto';

const ACCESS_SECRET = process.env.ACCESS_SECRET!;
const REFRESH_SECRET = process.env.REFRESH_SECRET!;

// In-memory store (use Redis in production)
const refreshTokens = new Map<string, { userId: string; family: string }>();

export function generateTokenPair(userId: string) {
  const family = crypto.randomUUID();
  const accessToken = jwt.sign({ sub: userId }, ACCESS_SECRET, { expiresIn: '15m' });
  const refreshToken = jwt.sign({ sub: userId, family }, REFRESH_SECRET, { expiresIn: '7d' });
  refreshTokens.set(refreshToken, { userId, family });
  return { accessToken, refreshToken };
}

export function rotateRefreshToken(oldToken: string) {
  const stored = refreshTokens.get(oldToken);
  if (!stored) throw new Error('Invalid refresh token');

  // Invalidate old token
  refreshTokens.delete(oldToken);

  // Verify and decode
  const payload = jwt.verify(oldToken, REFRESH_SECRET) as { sub: string; family: string };

  // Issue new pair with same family
  const accessToken = jwt.sign({ sub: payload.sub }, ACCESS_SECRET, { expiresIn: '15m' });
  const refreshToken = jwt.sign({ sub: payload.sub, family: stored.family }, REFRESH_SECRET, { expiresIn: '7d' });
  refreshTokens.set(refreshToken, { userId: stored.userId, family: stored.family });

  return { accessToken, refreshToken };
}

Use Cases

  • Secure API authentication
  • Session management

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.