The refresh token pattern helps keep users logged in safely without asking for their password again and again.
Refresh token pattern in NestJS
async refreshToken(oldRefreshToken: string): Promise<{ accessToken: string }> { // 1. Verify the old refresh token // 2. Check if it is valid and not expired // 3. Generate a new access token // 4. Optionally generate a new refresh token // 5. Return the new tokens }
The refresh token is usually stored securely and sent only when requesting a new access token.
Access tokens are short-lived; refresh tokens last longer and are used to get new access tokens.
async refreshToken(oldRefreshToken: string) { const payload = this.jwtService.verify(oldRefreshToken); if (!payload) throw new UnauthorizedException(); const newAccessToken = this.jwtService.sign({ userId: payload.userId }); return { accessToken: newAccessToken }; }
async refreshToken(oldRefreshToken: string) { const payload = this.jwtService.verify(oldRefreshToken, { secret: this.configService.get('REFRESH_TOKEN_SECRET') }); if (!payload) throw new UnauthorizedException(); const newAccessToken = this.jwtService.sign({ userId: payload.userId }); const newRefreshToken = this.jwtService.sign({ userId: payload.userId }, { expiresIn: '7d' }); return { accessToken: newAccessToken, refreshToken: newRefreshToken }; }
This NestJS service method checks the old refresh token. If valid, it creates new access and refresh tokens with different expiration times.
import { Injectable, UnauthorizedException } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; @Injectable() export class AuthService { constructor(private jwtService: JwtService) {} async refreshToken(oldRefreshToken: string): Promise<{ accessToken: string; refreshToken: string }> { try { const payload = this.jwtService.verify(oldRefreshToken, { secret: 'refreshSecret' }); const newAccessToken = this.jwtService.sign({ userId: payload.userId }, { expiresIn: '15m' }); const newRefreshToken = this.jwtService.sign({ userId: payload.userId }, { expiresIn: '7d', secret: 'refreshSecret' }); return { accessToken: newAccessToken, refreshToken: newRefreshToken }; } catch (e) { throw new UnauthorizedException('Invalid refresh token'); } } }
Always keep refresh tokens secret and store them securely, like in HttpOnly cookies.
Set short expiration for access tokens to reduce risk if stolen.
Handle errors carefully to avoid giving clues about token validity.
The refresh token pattern helps keep users logged in safely.
Use short-lived access tokens and longer-lived refresh tokens.
Verify refresh tokens before issuing new access tokens.
Practice
refresh token in a NestJS authentication system?Solution
Step 1: Understand token roles in authentication
Access tokens allow access but expire quickly; refresh tokens help get new access tokens without re-login.Step 2: Identify refresh token purpose
Refresh tokens are used to request new access tokens after expiration, keeping the user logged in safely.Final Answer:
To issue a new access token without requiring the user to log in again -> Option CQuick Check:
Refresh token = new access token without re-login [OK]
- Confusing refresh token with access token
- Thinking refresh token stores user credentials
- Assuming refresh token replaces access token permanently
Solution
Step 1: Identify JWT methods for token verification
In NestJS,jwtService.verify()checks token validity and signature.Step 2: Match method to refresh token verification
To verify a refresh token, usejwtService.verify(refreshToken)to confirm it is valid and not expired.Final Answer:
jwtService.verify(refreshToken) -> Option AQuick Check:
Verify token = jwtService.verify() [OK]
- Using sign() instead of verify() to check tokens
- Using decode() which does not verify signature
- Trying to encrypt tokens with jwtService
async refreshToken(token: string) {
try {
const payload = this.jwtService.verify(token);
const newAccessToken = this.jwtService.sign({ userId: payload.sub });
return { accessToken: newAccessToken };
} catch (e) {
throw new UnauthorizedException('Invalid refresh token');
}
}Solution
Step 1: Analyze token verification
The code verifies the refresh token; if valid, it extracts the payload.Step 2: Generate new access token
Using the payload's user ID, it signs a new access token and returns it in an object.Final Answer:
{ accessToken: 'newly_generated_token_string' } -> Option BQuick Check:
Valid refresh token returns new access token [OK]
- Assuming it returns the refresh token again
- Thinking it throws error on valid token
- Expecting null instead of token object
async refreshToken(token: string) {
const payload = this.jwtService.verify(token);
const newAccessToken = this.jwtService.sign({ userId: payload.userId });
return { accessToken: newAccessToken };
}Solution
Step 1: Check payload property usage
JWT payload usually stores user ID in 'sub' property, not 'userId'.Step 2: Identify mismatch causing error
Accessing 'payload.userId' will be undefined, causing incorrect token signing.Final Answer:
Incorrect property name 'userId' instead of 'sub' in payload -> Option DQuick Check:
JWT user ID = payload.sub, not payload.userId [OK]
- Ignoring missing try-catch for errors
- Assuming payload uses 'userId' key
- Confusing sign() and verify() methods
Solution
Step 1: Understand token invalidation
To invalidate old refresh tokens, you must track them server-side, usually in a database.Step 2: Implement token replacement logic
When issuing a new refresh token, delete or mark the old one invalid in the database to prevent reuse.Final Answer:
Store refresh tokens in a database and delete the old token when issuing a new one -> Option AQuick Check:
Invalidate old tokens by storing and deleting them [OK]
- Not storing tokens, so can't invalidate old ones
- Using refresh tokens without expiration
- Confusing access token with refresh token
Ready to prove it?
Pass the test and this pattern moves unknown
