From 066a195355337c58078faef90418fe63677fee75 Mon Sep 17 00:00:00 2001 From: Wilson Rivera Date: Fri, 1 Aug 2025 10:13:17 -0400 Subject: [PATCH 1/3] feat: improve session renewal --- controlplane/src/core/auth-utils.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/controlplane/src/core/auth-utils.ts b/controlplane/src/core/auth-utils.ts index 11f080fffb..17e6a3fdb5 100644 --- a/controlplane/src/core/auth-utils.ts +++ b/controlplane/src/core/auth-utils.ts @@ -305,10 +305,13 @@ export default class AuthUtils { // Check if the access token is expired const parsedAccessToken = decodeJWT(userSession.accessToken); - if (parsedAccessToken.exp && parsedAccessToken.exp < Date.now() / 1000) { - const parsedRefreshToken = decodeJWT(userSession.accessToken); + if (parsedAccessToken.exp && parsedAccessToken.exp < (Date.now() / 1000) + 15) { + if (!userSession.refreshToken) { + throw new AuthenticationError(EnumStatusCode.ERROR_NOT_AUTHENTICATED, 'No refresh token'); + } // Check if the refresh token is valid to issue a new access token + const parsedRefreshToken = decodeJWT(userSession.refreshToken); if (parsedRefreshToken.exp && parsedRefreshToken.exp < Date.now() / 1000) { throw new AuthenticationError(EnumStatusCode.ERROR_NOT_AUTHENTICATED, 'Refresh token expired'); } @@ -343,6 +346,7 @@ export default class AuthUtils { const jwt = await encrypt({ maxAgeInSeconds: sessionExpiresIn, token: { + iss: userSession.userId, sessionId: newUserSession.id, }, secret: this.opts.jwtSecret, From f2841afc3971ce0c21630012611a71d027ccd9e4 Mon Sep 17 00:00:00 2001 From: Wilson Rivera Date: Fri, 1 Aug 2025 10:15:03 -0400 Subject: [PATCH 2/3] chore: linting --- controlplane/src/core/auth-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controlplane/src/core/auth-utils.ts b/controlplane/src/core/auth-utils.ts index 17e6a3fdb5..b095aef9fb 100644 --- a/controlplane/src/core/auth-utils.ts +++ b/controlplane/src/core/auth-utils.ts @@ -305,7 +305,7 @@ export default class AuthUtils { // Check if the access token is expired const parsedAccessToken = decodeJWT(userSession.accessToken); - if (parsedAccessToken.exp && parsedAccessToken.exp < (Date.now() / 1000) + 15) { + if (parsedAccessToken.exp && parsedAccessToken.exp < Date.now() / 1000 + 15) { if (!userSession.refreshToken) { throw new AuthenticationError(EnumStatusCode.ERROR_NOT_AUTHENTICATED, 'No refresh token'); } From 8a1b13359a07e86eb4b93089eba342cfb9ae2985 Mon Sep 17 00:00:00 2001 From: Wilson Rivera Date: Wed, 6 Aug 2025 10:15:22 -0400 Subject: [PATCH 3/3] chore: increment token window skew to 5 minutes instead of 15 seconds --- controlplane/src/core/auth-utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/controlplane/src/core/auth-utils.ts b/controlplane/src/core/auth-utils.ts index b095aef9fb..1b895f88ae 100644 --- a/controlplane/src/core/auth-utils.ts +++ b/controlplane/src/core/auth-utils.ts @@ -37,6 +37,7 @@ export type AuthUtilsOptions = { }; }; +const tokenExpirationWindowSkew = 60 * 5; const pkceMaxAgeSec = 60 * 15; // 15 minutes const pkceCodeAlgorithm = 'S256'; const scope = 'openid profile email'; @@ -305,7 +306,7 @@ export default class AuthUtils { // Check if the access token is expired const parsedAccessToken = decodeJWT(userSession.accessToken); - if (parsedAccessToken.exp && parsedAccessToken.exp < Date.now() / 1000 + 15) { + if (parsedAccessToken.exp && parsedAccessToken.exp < Date.now() / 1000 + tokenExpirationWindowSkew) { if (!userSession.refreshToken) { throw new AuthenticationError(EnumStatusCode.ERROR_NOT_AUTHENTICATED, 'No refresh token'); }