From fa2b63de40e285d12efb8cf1c68f32edd6f18f0f Mon Sep 17 00:00:00 2001 From: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com> Date: Wed, 15 Oct 2025 17:01:56 +0200 Subject: [PATCH] chore: apply requested changes p2 --- .../tm-core/src/auth/credential-store.spec.ts | 19 ++++++++++++++ .../tm-core/src/auth/credential-store.test.ts | 25 +++++++++++++++++++ packages/tm-core/src/auth/credential-store.ts | 4 +-- .../tm-core/tests/auth/auth-refresh.test.ts | 8 +++--- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/packages/tm-core/src/auth/credential-store.spec.ts b/packages/tm-core/src/auth/credential-store.spec.ts index e28e3403..9ac43d0d 100644 --- a/packages/tm-core/src/auth/credential-store.spec.ts +++ b/packages/tm-core/src/auth/credential-store.spec.ts @@ -92,6 +92,25 @@ describe('CredentialStore - Token Expiration', () => { expect(retrieved).not.toBeNull(); expect(retrieved?.token).toBe('expired-token'); }); + + it('should return expired token by default (allowExpired defaults to true)', () => { + const expiredCredentials: AuthCredentials = { + token: 'expired-token-default', + refreshToken: 'refresh-token', + userId: 'test-user', + email: 'test@example.com', + expiresAt: new Date(Date.now() - 60000).toISOString(), + savedAt: new Date().toISOString() + }; + + credentialStore.saveCredentials(expiredCredentials); + + // Call without options - should default to allowExpired: true + const retrieved = credentialStore.getCredentials(); + + expect(retrieved).not.toBeNull(); + expect(retrieved?.token).toBe('expired-token-default'); + }); }); describe('Clock Skew Tolerance', () => { diff --git a/packages/tm-core/src/auth/credential-store.test.ts b/packages/tm-core/src/auth/credential-store.test.ts index 7da16917..ce35b36b 100644 --- a/packages/tm-core/src/auth/credential-store.test.ts +++ b/packages/tm-core/src/auth/credential-store.test.ts @@ -226,6 +226,31 @@ describe('CredentialStore', () => { expect(result).not.toBeNull(); expect(result?.token).toBe('expired-token'); }); + + it('should return expired tokens by default (allowExpired defaults to true)', () => { + const expiredTimestamp = Date.now() - 3600000; // 1 hour ago + const mockCredentials = { + token: 'expired-token-default', + userId: 'user-expired', + expiresAt: expiredTimestamp, + tokenType: 'standard', + savedAt: new Date().toISOString() + }; + + vi.mocked(fs.existsSync).mockReturnValue(true); + vi.mocked(fs.readFileSync).mockReturnValue( + JSON.stringify(mockCredentials) + ); + + // Call without options - should default to allowExpired: true + const result = store.getCredentials(); + + expect(result).not.toBeNull(); + expect(result?.token).toBe('expired-token-default'); + expect(mockLogger.warn).not.toHaveBeenCalledWith( + expect.stringContaining('Authentication token has expired') + ); + }); }); describe('saveCredentials with timestamp normalization', () => { diff --git a/packages/tm-core/src/auth/credential-store.ts b/packages/tm-core/src/auth/credential-store.ts index 8f7a6f31..fd1983c3 100644 --- a/packages/tm-core/src/auth/credential-store.ts +++ b/packages/tm-core/src/auth/credential-store.ts @@ -89,7 +89,7 @@ export class CredentialStore { authData.expiresAt = expiresAtMs; // Check if the token has expired (with clock skew tolerance) - // Default to allowExpired=true so Supabase can access refresh tokens + // Default to allowExpired=true to enable refresh flows const now = Date.now(); const allowExpired = options?.allowExpired ?? true; if (now >= expiresAtMs - this.CLOCK_SKEW_MS && !allowExpired) { @@ -104,7 +104,7 @@ export class CredentialStore { return null; } - // Return credentials (even if expired, so Supabase can refresh) + // Return credentials (even if expired) to enable refresh flows return authData; } catch (error) { this.logger.error( diff --git a/packages/tm-core/tests/auth/auth-refresh.test.ts b/packages/tm-core/tests/auth/auth-refresh.test.ts index ec3fbf5f..0ae4f357 100644 --- a/packages/tm-core/tests/auth/auth-refresh.test.ts +++ b/packages/tm-core/tests/auth/auth-refresh.test.ts @@ -50,7 +50,7 @@ describe('AuthManager Token Refresh', () => { } }); - it('should return expired credentials for Supabase to refresh', () => { + it('should return expired credentials to enable refresh flows', () => { // Set up expired credentials with refresh token const expiredCredentials: AuthCredentials = { token: 'expired_access_token', @@ -64,7 +64,7 @@ describe('AuthManager Token Refresh', () => { credentialStore.saveCredentials(expiredCredentials); // Get credentials should return them even if expired - // Supabase will handle the refresh automatically + // Refresh will be handled by explicit calls or client operations const credentials = authManager.getCredentials(); expect(credentials).not.toBeNull(); @@ -92,7 +92,7 @@ describe('AuthManager Token Refresh', () => { it('should return expired credentials even without refresh token', () => { // Set up expired credentials WITHOUT refresh token - // We still return them - it's up to the caller/Supabase to handle + // We still return them - it's up to the caller to handle const expiredCredentials: AuthCredentials = { token: 'expired_access_token', refreshToken: undefined, @@ -131,7 +131,7 @@ describe('AuthManager Token Refresh', () => { const credentials = authManager.getCredentials(); - // Returns credentials - Supabase will attempt refresh and handle failure + // Returns credentials - refresh will be attempted by the client which will handle failure expect(credentials).not.toBeNull(); expect(credentials?.token).toBe('expired_access_token'); expect(credentials?.refreshToken).toBe('invalid_refresh_token');