diff --git a/plugins/auth-backend-module-auth0-provider/src/authenticator.test.ts b/plugins/auth-backend-module-auth0-provider/src/authenticator.test.ts index 0fdeb87cdb..aebb73812c 100644 --- a/plugins/auth-backend-module-auth0-provider/src/authenticator.test.ts +++ b/plugins/auth-backend-module-auth0-provider/src/authenticator.test.ts @@ -242,4 +242,47 @@ describe('createAuth0Authenticator', () => { expect(mockFetchProfile).toHaveBeenCalledTimes(2); expect(result.fullProfile).toEqual(updatedProfile); }); + + it('should skip cache when id_token has no sub claim', async () => { + const header = Buffer.from(JSON.stringify({ alg: 'none' })).toString( + 'base64url', + ); + const payload = Buffer.from(JSON.stringify({ aud: 'test' })).toString( + 'base64url', + ); + const idTokenWithoutSub = `${header}.${payload}.`; + + mockExecuteRefresh.mockResolvedValue({ + accessToken: 'new-access-token', + refreshToken: 'new-refresh-token', + params: { + token_type: 'bearer', + scope: 'openid profile', + expires_in: 3600, + id_token: idTokenWithoutSub, + }, + }); + + const authenticator = createAuth0Authenticator({ cache }); + const ctx = authenticator.initialize({ + callbackUrl: 'http://localhost/callback', + config: mockConfig, + }); + + const result = await authenticator.refresh( + { + refreshToken: 'my-refresh-token', + scope: 'openid profile', + req: {} as express.Request, + }, + ctx, + ); + + // Profile is fetched directly + expect(mockFetchProfile).toHaveBeenCalledWith('new-access-token'); + expect(result.fullProfile).toEqual(mockProfile); + // Cache is never read or written + expect(cache.get).not.toHaveBeenCalled(); + expect(cache.set).not.toHaveBeenCalled(); + }); }); diff --git a/plugins/auth-backend-module-auth0-provider/src/authenticator.ts b/plugins/auth-backend-module-auth0-provider/src/authenticator.ts index 6390324869..c22705a165 100644 --- a/plugins/auth-backend-module-auth0-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-auth0-provider/src/authenticator.ts @@ -140,17 +140,20 @@ export function createAuth0Authenticator(options?: { cache?: CacheService }) { ); const { sub } = decodeJwt(result.params.id_token); - const cacheKey = `auth0-profile:${sub}`; - let fullProfile = (await profileCache?.get(cacheKey)) as - | PassportProfile - | undefined; + const cacheKey = sub ? `auth0-profile:${sub}` : undefined; + + let fullProfile = cacheKey + ? ((await profileCache?.get(cacheKey)) as PassportProfile | undefined) + : undefined; if (!fullProfile) { fullProfile = await helper.fetchProfile(result.accessToken); - await profileCache?.set( - cacheKey, - JSON.parse(JSON.stringify(fullProfile)), - ); + if (cacheKey) { + await profileCache?.set( + cacheKey, + JSON.parse(JSON.stringify(fullProfile)), + ); + } } return {