From 269b4c1786200603268524b74e032b20bcc4cfce Mon Sep 17 00:00:00 2001 From: Spencer Post Date: Thu, 28 Mar 2024 19:34:12 -0600 Subject: [PATCH] pass scopes to strategy Signed-off-by: Spencer Post --- .changeset/curly-seals-pull.md | 5 ++ .../config.d.ts | 1 + .../src/authenticator.ts | 4 ++ .../src/module.test.ts | 57 +++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 .changeset/curly-seals-pull.md diff --git a/.changeset/curly-seals-pull.md b/.changeset/curly-seals-pull.md new file mode 100644 index 0000000000..eba8b5c0b2 --- /dev/null +++ b/.changeset/curly-seals-pull.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-atlassian-provider': patch +--- + +Read scopes from config and pass to AtlassianProvider as they are required diff --git a/plugins/auth-backend-module-atlassian-provider/config.d.ts b/plugins/auth-backend-module-atlassian-provider/config.d.ts index 999bf1b304..57def03aab 100644 --- a/plugins/auth-backend-module-atlassian-provider/config.d.ts +++ b/plugins/auth-backend-module-atlassian-provider/config.d.ts @@ -27,6 +27,7 @@ export interface Config { clientSecret: string; audience?: string; callbackUrl?: string; + scope?: string; }; }; }; diff --git a/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts b/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts index 340c61052c..0538d8d742 100644 --- a/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts @@ -29,6 +29,9 @@ export const atlassianAuthenticator = createOAuthAuthenticator({ initialize({ callbackUrl, config }) { const clientId = config.getString('clientId'); const clientSecret = config.getString('clientSecret'); + const scope = + config.getOptionalString('scope') || + 'offline_access read:jira-work read:jira-user'; const baseUrl = 'https://auth.atlassian.com'; return PassportOAuthAuthenticatorHelper.from( @@ -41,6 +44,7 @@ export const atlassianAuthenticator = createOAuthAuthenticator({ authorizationURL: `${baseUrl}/authorize`, tokenURL: `${baseUrl}/oauth/token`, profileURL: `${baseUrl}/api/v4/user`, + scope, }, ( accessToken: string, diff --git a/plugins/auth-backend-module-atlassian-provider/src/module.test.ts b/plugins/auth-backend-module-atlassian-provider/src/module.test.ts index 024a45d43d..213df4b0fc 100644 --- a/plugins/auth-backend-module-atlassian-provider/src/module.test.ts +++ b/plugins/auth-backend-module-atlassian-provider/src/module.test.ts @@ -67,6 +67,63 @@ describe('authModuleAtlassianProvider', () => { client_id: 'my-client-id', redirect_uri: `http://localhost:${server.port()}/api/auth/atlassian/handler/frame`, state: expect.any(String), + scope: 'offline_access read:jira-work read:jira-user', + }); + + expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ + env: 'development', + nonce: decodeURIComponent(nonceCookie.value), + }); + }); + it('should start with and use custom scopes', async () => { + const { server } = await startTestBackend({ + features: [ + import('@backstage/plugin-auth-backend'), + authModuleAtlassianProvider, + mockServices.rootConfig.factory({ + data: { + app: { + baseUrl: 'http://localhost:3000', + }, + auth: { + providers: { + atlassian: { + development: { + clientId: 'my-client-id', + clientSecret: 'my-client-secret', + scope: 'offline_access read:filter:jira read:jira-work', + }, + }, + }, + }, + }, + }), + ], + }); + + const agent = request.agent(server); + + const res = await agent.get('/api/auth/atlassian/start?env=development'); + + expect(res.status).toEqual(302); + + const nonceCookie = agent.jar.getCookie('atlassian-nonce', { + domain: 'localhost', + path: '/api/auth/atlassian/handler', + script: false, + secure: false, + }); + expect(nonceCookie).toBeDefined(); + + const startUrl = new URL(res.get('location')); + expect(startUrl.origin).toBe('https://auth.atlassian.com'); + expect(startUrl.pathname).toBe('/authorize'); + expect(Object.fromEntries(startUrl.searchParams)).toEqual({ + response_type: 'code', + client_id: 'my-client-id', + redirect_uri: `http://localhost:${server.port()}/api/auth/atlassian/handler/frame`, + state: expect.any(String), + scope: 'offline_access read:filter:jira read:jira-work', }); expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({