diff --git a/.changeset/orange-chefs-end.md b/.changeset/orange-chefs-end.md new file mode 100644 index 0000000000..9ba2a29685 --- /dev/null +++ b/.changeset/orange-chefs-end.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-oidc-provider': patch +--- + +if oidc server do not provide revocation_endpoint,we should not call revoke function diff --git a/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts b/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts index 4f1db097d0..67bfd27b19 100644 --- a/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts +++ b/plugins/auth-backend-module-oidc-provider/src/authenticator.test.ts @@ -493,5 +493,52 @@ describe('oidcAuthenticator', () => { new Error('Refresh failed'), ); }); + + it('should not revoke refreshToken when issuer revocation_endpoint is undefined', async () => { + const refreshToken = 'revokeRefreshToken2'; + const refreshRequest = { + scope: 'testScope', + refreshToken, + req: {} as express.Request, + }; + const logoutRequest = { + refreshToken, + req: {} as express.Request, + }; + + // override .well-known endpoint response, set revocation_endpoint to undefined + mswServer.use( + rest.get( + 'https://oidc.test/.well-known/openid-configuration', + (_req, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/json'), + ctx.json({ + ...issuerMetadata, + revocation_endpoint: undefined, + }), + ), + ), + ); + + const newImplementation = oidcAuthenticator.initialize({ + callbackUrl: 'https://backstage.test/callback', + config: new ConfigReader({ + metadataUrl: 'https://oidc.test/.well-known/openid-configuration', + clientId: 'clientId', + clientSecret: 'clientSecret', + }), + }); + + await oidcAuthenticator.logout?.(logoutRequest, newImplementation); + + const refreshResponse = await oidcAuthenticator.refresh( + refreshRequest, + newImplementation, + ); + + expect(refreshResponse.session.refreshToken).toBe('refreshToken'); + }); }); }); diff --git a/plugins/auth-backend-module-oidc-provider/src/authenticator.ts b/plugins/auth-backend-module-oidc-provider/src/authenticator.ts index f954d228e2..2b6a9b34f1 100644 --- a/plugins/auth-backend-module-oidc-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-oidc-provider/src/authenticator.ts @@ -202,8 +202,15 @@ export const oidcAuthenticator = createOAuthAuthenticator({ async logout(input, ctx) { const { client } = await ctx.promise; + const issuer = client.issuer; + /** + * https://github.com/panva/node-openid-client/blob/main/lib/client.js#L1398 + * client.revoke will check revocation_endpoint and if undefined throw error。 + * + * if oidc server do not provide revocation_endpoint,we should not call revoke function + */ - if (input.refreshToken) { + if (input.refreshToken && issuer.revocation_endpoint) { await client.revoke(input.refreshToken); } },