Skip to content

NestJS Refresh Tokens

Access tokens should be short-lived. Refresh tokens let clients obtain new access tokens without forcing the user to log in again. This lesson covers a practical Nest refresh-token design.

Access Token + Refresh Token Pair

On login, issue a short-lived access JWT and a longer-lived refresh token. Store a hash of the refresh token server-side (or in a dedicated table). Clients call POST /auth/refresh with the refresh token to receive a new access token (and preferably a rotated refresh token).

@Post('refresh')
async refresh(@Body('refreshToken') refreshToken: string) {
  const userId = await this.authService.validateRefreshToken(refreshToken);
  return this.authService.issueTokens(userId);
}

Always rotate refresh tokens on use when possible: invalidate the old one and issue a new pair to reduce replay risk.

Safe Refresh Token Storage

// store hashed refresh token
await this.usersService.setRefreshTokenHash(userId, await bcrypt.hash(rawToken, 10));

// verify later
const valid = await bcrypt.compare(rawToken, user.refreshTokenHash);
  • Never store raw refresh tokens in the database.
  • Bind refresh tokens to a user (and optionally device/session id).
  • Provide a logout endpoint that clears the stored refresh hash.
  • Reject reuse of an already-rotated refresh token (possible theft signal).

Refresh Token Cheatsheet

Practices for Nest refresh-token flows.

Practice Why
Short access token TTL Limits damage from leaked bearer tokens
Rotate refresh tokens Detects token replay/theft
Hash server-side storage DB leaks do not expose usable tokens
Logout clears hash Ends the refresh capability immediately
Separate secrets (optional) Sign access and refresh with different keys

Reuse Detection

If a refresh token is presented after it was already rotated, treat it as suspicious: revoke all sessions for that user and force re-login.

Common Mistakes

  • Making access tokens long-lived and skipping refresh tokens entirely.
  • Storing refresh tokens in plaintext in the database.
  • Never invalidating refresh tokens on logout or password change.
  • Returning refresh tokens in URLs or logs.

Key Takeaways

  • Refresh tokens extend sessions without long-lived access JWTs.
  • Hash and rotate refresh tokens; clear them on logout.
  • Reuse of old refresh tokens should revoke sessions.
  • Transport choice (cookie vs body) depends on client type and threat model.

Pro Tip

On password change or "log out everywhere", wipe all refresh-token hashes for that user so old devices cannot mint new access tokens.