Script Valley
JWT & Session Auth: Deep Dive
JWT Deep DiveLesson 2.3

JWT expiry and refresh token strategy

short-lived access tokens, long-lived refresh tokens, refresh token rotation, token family tracking, silent refresh, refresh endpoint implementation

JWT Expiry and Refresh Token Strategy

JWT Refresh Token Flow

Short-lived JWTs (15 minutes) limit the damage window if a token is stolen. But forcing users to log in every 15 minutes is unacceptable. Refresh tokens solve this.

The pattern:

  1. On login, issue two tokens: an access token (15mโ€“1h TTL) and a refresh token (7โ€“30d TTL).
  2. Store the refresh token in an HttpOnly cookie or server-side.
  3. When the access token expires, the client hits POST /auth/refresh with the refresh token.
  4. Server validates the refresh token, issues a new access token (and optionally a new refresh token โ€” rotation).
// Refresh endpoint
app.post('/auth/refresh', (req, res) => {
  const refreshToken = req.cookies.refreshToken;
  if (!refreshToken) return res.status(401).json({ error: 'No refresh token' });

  try {
    const payload = jwt.verify(refreshToken, process.env.REFRESH_SECRET);
    const newAccessToken = jwt.sign(
      { sub: payload.sub, role: payload.role },
      process.env.JWT_SECRET,
      { expiresIn: '15m' }
    );
    res.json({ accessToken: newAccessToken });
  } catch {
    res.status(401).json({ error: 'Invalid refresh token' });
  }
});

Refresh token rotation means issuing a new refresh token on every use and invalidating the old one. This limits refresh token theft windows and enables detection of token reuse (a reused old refresh token signals compromise).

Up next

JWT security pitfalls: algorithm confusion and none attack

Sign in to track progress

JWT expiry and refresh token strategy โ€” JWT Deep Dive โ€” JWT & Session Auth: Deep Dive โ€” Script Valley โ€” Script Valley