From 80fc6573b73f4a77a0e2f37bdb0e55955d659062 Mon Sep 17 00:00:00 2001 From: Loris Date: Sun, 20 Jul 2025 20:21:13 +0200 Subject: [PATCH] feat(rotation): option to enable refresh token rotation --- .env.example | 1 + src/configs/auth.config.ts | 1 + src/modules/auth/services/auth.service.ts | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 266f7b5b5..e229d45cd 100644 --- a/.env.example +++ b/.env.example @@ -36,6 +36,7 @@ AUTH_JWT_REFRESH_TOKEN_KID= AUTH_JWT_REFRESH_TOKEN_PRIVATE_KEY_PATH=keys/refresh-token.pem AUTH_JWT_REFRESH_TOKEN_PUBLIC_KEY_PATH=keys/refresh-token.pub AUTH_JWT_REFRESH_TOKEN_EXPIRED=7d +AUTH_JWT_REFRESH_TOKEN_ROTATE_ON_RENEWAL=true AUTH_SOCIAL_GOOGLE_CLIENT_ID= AUTH_SOCIAL_GOOGLE_CLIENT_SECRET= diff --git a/src/configs/auth.config.ts b/src/configs/auth.config.ts index 85fef00ba..6e5055b94 100644 --- a/src/configs/auth.config.ts +++ b/src/configs/auth.config.ts @@ -29,6 +29,7 @@ export default registerAs( process.env .AUTH_JWT_REFRESH_TOKEN_EXPIRED as ms.StringValue ) / 1000, + rotateOnRenewal: process.env.AUTH_JWT_REFRESH_TOKEN_ROTATE_ON_RENEWAL === 'true', }, algorithm: 'ES512', diff --git a/src/modules/auth/services/auth.service.ts b/src/modules/auth/services/auth.service.ts index 790d5f1a7..f6ac25c6c 100644 --- a/src/modules/auth/services/auth.service.ts +++ b/src/modules/auth/services/auth.service.ts @@ -34,6 +34,7 @@ export class AuthService implements IAuthService { private readonly jwtRefreshTokenPrivateKey: string; private readonly jwtRefreshTokenPublicKey: string; private readonly jwtRefreshTokenExpirationTime: number; + private readonly jwtRefreshTokenRotateOnRenewal: boolean; private readonly jwtPrefix: string; private readonly jwtAudience: string; @@ -111,6 +112,9 @@ export class AuthService implements IAuthService { this.jwtRefreshTokenExpirationTime = this.configService.get( 'auth.jwt.refreshToken.expirationTime' ); + this.jwtRefreshTokenRotateOnRenewal = this.configService.get( + 'auth.jwt.refreshToken.rotateOnRenewal' + ); this.jwtPrefix = this.configService.get('auth.jwt.prefix'); this.jwtAudience = this.configService.get('auth.jwt.audience'); @@ -349,12 +353,22 @@ export class AuthService implements IAuthService { payloadAccessToken ); + let refreshToken: string = refreshTokenFromRequest + if (this.jwtRefreshTokenRotateOnRenewal) { + const payloadRefreshToken: IAuthJwtRefreshTokenPayload = + this.createPayloadRefreshToken(payloadAccessToken); + refreshToken = this.createRefreshToken( + user._id, + payloadRefreshToken + ); + } + return { tokenType: this.jwtPrefix, roleType, expiresIn: this.jwtAccessTokenExpirationTime, accessToken, - refreshToken: refreshTokenFromRequest, + refreshToken, }; }