@rs-tech-hub/nestjs-refresh-token
Refresh token management for NestJS applications. Create, validate, revoke, and manage JWT refresh tokens with automatic expiry and cleanup.
๐ Table of Contents
- ๐ License
- โจ Features
- ๐ Prerequisites
- ๐ฆ Installation
- ๐ Module Registration
- ๐ป Service Usage
- ๐ง Repository Usage
- ๐ API Reference
- ๐ Data Model
- โ ๏ธ Error Codes
- ๐ก Best Practices
- ๐ Typical Token Refresh Flow
- ๐ License
- ๐ Release Notes
- ๐ Support
๐ Related Documentation
- Auth Core - JWT refresh token strategy
- Auth Starter - Token refresh implementation
- User Module - User association
- Clock Module - Token expiration management
- Prisma Module - Token persistence
๐ License
This package requires a valid commercial license. A valid license key must be configured to use this package.
Visit https://rstechhub.gumroad.com to purchase a license.
โจ Features
- ๐ Token Generation - Create unique refresh tokens with UUID
- โฐ Expiry Management - Configurable token expiration (default 7 days)
- ๐ซ Token Revocation - Revoke individual or all user tokens
- ๐งน Automatic Cleanup - Remove expired and revoked tokens
- ๐ Token Validation - Find and validate tokens by value
- ๐ค User Association - Link tokens to specific users
- ๐ Token Replacement - Track token replacement chains
๐ Prerequisites
- Node.js โฅ 18
- TypeScript โฅ 5.1.0
- NestJS โฅ 11.1.6
- Prisma ORM v7.0+
๐ฆ Installation
npm install @rs-tech-hub/nestjs-refresh-token \
@rs-tech-hub/nestjs-clock \
@rs-tech-hub/nestjs-license-validator \
@rs-tech-hub/nestjs-prisma \
@rs-tech-hub/nestjs-service-operation \
@rs-tech-hub/nestjs-user \
uuid
yarn add @rs-tech-hub/nestjs-refresh-token \
@rs-tech-hub/nestjs-clock \
@rs-tech-hub/nestjs-license-validator \
@rs-tech-hub/nestjs-prisma \
@rs-tech-hub/nestjs-service-operation \
@rs-tech-hub/nestjs-user \
uuid
pnpm add @rs-tech-hub/nestjs-refresh-token \
@rs-tech-hub/nestjs-clock \
@rs-tech-hub/nestjs-license-validator \
@rs-tech-hub/nestjs-prisma \
@rs-tech-hub/nestjs-service-operation \
@rs-tech-hub/nestjs-user \
uuid
๐ Module Registration
Import the module in your NestJS application:
import { Module } from "@nestjs/common";
import { RefreshTokenModule } from "@rs-tech-hub/nestjs-refresh-token";
@Module({
imports: [RefreshTokenModule],
})
export class AppModule {}
๐ป Service Usage
Creating Refresh Tokens
import { Injectable } from "@nestjs/common";
import { RefreshTokenService } from "@rs-tech-hub/nestjs-refresh-token";
@Injectable()
export class AuthService {
constructor(private refreshTokenService: RefreshTokenService) {}
async login(userId: string) {
// Create a refresh token (expires in 7 days by default)
const refreshToken = await this.refreshTokenService.createRefreshToken(
userId
);
// Or specify custom expiry in days
const longLivedToken = await this.refreshTokenService.createRefreshToken(
userId,
30
);
return {
accessToken: "jwt-access-token",
refreshToken,
};
}
}
Finding Tokens
// Find token by token value
const tokenData = await this.refreshTokenService.findByToken(tokenString);
// Find user ID by token
const userIdData = await this.refreshTokenService.findUserIdByToken(
tokenString
);
// Find all active tokens for a user
const activeTokens = await this.refreshTokenService.findActiveTokensForUser(
userId
);
Revoking Tokens
// Revoke a specific token by ID
await this.refreshTokenService.revokeToken(tokenId);
// Revoke token by token value
await this.refreshTokenService.revokeTokenByValue(tokenString);
// Revoke token and specify replacement
await this.refreshTokenService.revokeToken(oldTokenId, newTokenString);
// Revoke all tokens for a user
const result = await this.refreshTokenService.revokeAllUserTokens(userId);
Token Cleanup
// Clean up expired tokens (retention period: 60 days)
await this.refreshTokenService.cleanupExpiredTokens();
// Delete all expired and revoked tokens
const deletedCount =
await this.refreshTokenService.deleteExpiredAndRevokedTokens();
๐ง Repository Usage
The package also exports RefreshTokenRepository for direct database access:
import { Injectable } from "@nestjs/common";
import { RefreshTokenRepository } from "@rs-tech-hub/nestjs-refresh-token";
@Injectable()
export class TokenManagementService {
constructor(private refreshTokenRepo: RefreshTokenRepository) {}
async getTokensByUser(userId: string) {
return this.refreshTokenRepo.findMany({ userId });
}
async deleteToken(tokenId: string) {
return this.refreshTokenRepo.delete({ id: tokenId });
}
async countUserTokens(userId: string) {
return this.refreshTokenRepo.count({ userId });
}
}
๐ API Reference
RefreshTokenService Methods
createRefreshToken(userId: string, expiryDays?: number): Promise<string>
Create a new refresh token for a user.
Parameters:
userId- The ID of the userexpiryDays- Token expiry in days (default: 7)
Returns: The token string (UUID v4)
findByToken(token: string): Promise<RefreshTokenServiceOutput>
Find a refresh token by its token value.
Returns: Token data including id, userId, expiresAt, revoked status
findUserIdByToken(token: string): Promise<{ userId: string }>
Find the user ID associated with a token.
Returns: Object containing userId
findActiveTokensForUser(userId: string): Promise<RefreshTokenServiceOutput[]>
Find all active (not revoked and not expired) tokens for a user.
Returns: Array of active refresh tokens
revokeToken(tokenId: string, replacedByToken?: string): Promise<RefreshTokenServiceOutput>
Revoke a refresh token by its ID.
Parameters:
tokenId- The ID of the token to revokereplacedByToken- Optional new token that replaces this one
Returns: The updated token
revokeTokenByValue(token: string, replacedByToken?: string): Promise<RefreshTokenServiceOutput>
Revoke a refresh token by its token value.
Parameters:
token- The token string to revokereplacedByToken- Optional new token that replaces this one
Returns: The updated token
revokeAllUserTokens(userId: string): Promise<ServiceResult<string, boolean>>
Revoke all tokens for a specific user.
Returns: ServiceResult indicating success or failure
cleanupExpiredTokens(): Promise<ServiceResult>
Delete expired and old revoked tokens (60 day retention period).
Returns: ServiceResult with deletion count
deleteExpiredAndRevokedTokens(): Promise<number>
Delete all expired and revoked tokens immediately.
Returns: Number of deleted tokens
๐ Data Model
RefreshTokenModel
{
id: string; // Unique token ID
token: string; // UUID v4 token value
userId: string; // Associated user ID
revoked: boolean; // Revocation status
replacedByToken?: string; // Token that replaced this one
expiresAt: Date; // Expiration date
createdAt: Date; // Creation timestamp
updatedAt: Date; // Last update timestamp
}
โ ๏ธ Error Codes
| Error Code | Description |
|---|---|
user-error:refresh-token-expired | Token has expired |
user-error:refresh-token-invalid | Token is invalid or not found |
user-error:refresh-token-revoked | Token has been revoked |
๐ก Best Practices
- Token Rotation: Always revoke old tokens when issuing new ones
- Regular Cleanup: Run
cleanupExpiredTokens()periodically (e.g., daily cron job) - Expiry Duration: Use appropriate expiry times (7-30 days recommended)
- Revoke on Logout: Always revoke tokens when users log out
- Track Replacements: Use
replacedByTokenparameter to track token chains - Validate Before Use: Always check token status before issuing new access tokens
- Limit Active Tokens: Consider limiting the number of active tokens per user
๐ Typical Token Refresh Flow
@Injectable()
export class AuthService {
constructor(
private refreshTokenService: RefreshTokenService,
private jwtService: JwtService
) {}
async refreshAccessToken(refreshToken: string) {
// 1. Find the refresh token
const tokenData = await this.refreshTokenService.findByToken(refreshToken);
// 2. Validate token
if (!tokenData) {
throw new Error("user-error:refresh-token-invalid");
}
if (tokenData.revoked) {
throw new Error("user-error:refresh-token-revoked");
}
if (tokenData.expiresAt < new Date()) {
throw new Error("user-error:refresh-token-expired");
}
// 3. Generate new tokens
const accessToken = this.jwtService.sign({ sub: tokenData.userId });
const newRefreshToken = await this.refreshTokenService.createRefreshToken(
tokenData.userId
);
// 4. Revoke old refresh token and link to new one
await this.refreshTokenService.revokeToken(tokenData.id, newRefreshToken);
return {
accessToken,
refreshToken: newRefreshToken,
};
}
}
๐ License
This package requires a valid commercial license. See LICENSE.txt for details. By using this software, you agree to the terms outlined in the Software License Agreement (SLA.md). The license grants you specific rights to use, modify, and deploy the software within the scope defined in the agreement. For full terms, conditions, and restrictions, please refer to the Software License Agreement.
๐ Release Notes
1.0.0
- Initial release
1.0.1
- Updates RefreshTokenService
๐ Support
For technical support and inquiries:
- Email: insights@rs-tech-hub.com
- Website: https://rs-tech-hub.com