From 144a3b9294c42c4a601696c280e1aa0461b70bd9 Mon Sep 17 00:00:00 2001 From: Nicholas Pirrello Date: Thu, 25 Jun 2020 18:20:13 -0400 Subject: [PATCH] Fix build and add okta oauth2 scope normalization --- .../auth/okta/OktaAuth.test.ts | 18 +++++++++++++++ .../implementations/auth/okta/OktaAuth.ts | 22 +++++++++++++++++-- packages/storybook/.storybook/apis.js | 11 ++++++++++ .../src/providers/okta/provider.ts | 4 ++-- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.test.ts b/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.test.ts index 7f2bd5d6bc..ab6c46c9b4 100644 --- a/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.test.ts +++ b/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.test.ts @@ -18,6 +18,8 @@ import OktaAuth from './OktaAuth'; const theFuture = new Date(Date.now() + 3600000); const thePast = new Date(Date.now() - 10); +const PREFIX = 'okta.'; + describe('OktaAuth', () => { it('should get refreshed access token', async () => { const getSession = jest.fn().mockResolvedValue({ @@ -108,4 +110,20 @@ describe('OktaAuth', () => { await expect(promise3).resolves.toBe('token2'); expect(getSession).toBeCalledTimes(4); // De-duping of session requests happens in client }); + + it.each([ + ['openid', ['openid']], + ['profile email', ['profile', 'email']], + [`${PREFIX}groups.manage`, [`${PREFIX}groups.manage`]], + ['groups.read', [`${PREFIX}groups.read`]], + [`${PREFIX}groups.manage groups.read, openid`, [`${PREFIX}groups.manage`, `${PREFIX}groups.read`, 'openid']], + [`email\t ${PREFIX}groups.read`, ['email', `${PREFIX}groups.read`]], + + // Some incorrect scopes that we don't try to fix + [`${PREFIX}email`, [`${PREFIX}email`]], + [`${PREFIX}profile`, [`${PREFIX}profile`]], + [`${PREFIX}openid`, [`${PREFIX}openid`]], + ])(`should normalize scopes correctly - %p`, (scope, scopes) => { + expect(OktaAuth.normalizeScopes(scope)).toEqual(new Set(scopes)); + }); }); diff --git a/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.ts b/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.ts index 55820375f6..5631648016 100644 --- a/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.ts +++ b/packages/core-api/src/apis/implementations/auth/okta/OktaAuth.ts @@ -60,6 +60,12 @@ const DEFAULT_PROVIDER = { icon: OktaIcon, }; +const OKTA_OIDC_SCOPES: Set = new Set( + ['openid', 'profile', 'email', 'phone', 'address', 'groups', 'offline_access'] +) + +const OKTA_SCOPE_PREFIX: string = 'okta.' + class OktaAuth implements OAuthApi, OpenIdConnectApi, @@ -152,7 +158,7 @@ class OktaAuth implements return session?.profile; } - static normalizeScopes(scope?: string): Set { + static normalizeScopes(scope?: string | string[]): Set { if (!scope) { return new Set(); } @@ -161,7 +167,19 @@ class OktaAuth implements ? scope : scope.split(/[\s|,]/).filter(Boolean); - return new Set(scopeList); + const normalizedScopes = scopeList.map(scope => { + if (OKTA_OIDC_SCOPES.has(scope)) { + return scope; + } + + if (scope.startsWith(OKTA_SCOPE_PREFIX)) { + return scope; + } + + return `${OKTA_SCOPE_PREFIX}${scope}` + }); + + return new Set(normalizedScopes); } } diff --git a/packages/storybook/.storybook/apis.js b/packages/storybook/.storybook/apis.js index 3b61ae7af8..0d0cf74e8f 100644 --- a/packages/storybook/.storybook/apis.js +++ b/packages/storybook/.storybook/apis.js @@ -6,11 +6,13 @@ import { OAuthRequestManager, googleAuthApiRef, githubAuthApiRef, + oktaAuthApiRef, AlertApiForwarder, ErrorApiForwarder, ErrorAlerter, GoogleAuth, GithubAuth, + OktaAuth, identityApiRef, } from '@backstage/core'; @@ -50,4 +52,13 @@ builder.add( }), ); +builder.add( + oktaAuthApiRef, + OktaAuth.create({ + apiOrigin: 'http://localhost:7000', + basePath: '/auth/', + oauthRequestApi, + }), +); + export const apis = builder.build(); diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts index 7b3d5770d7..788af9c4bd 100644 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ b/plugins/auth-backend/src/providers/okta/provider.ts @@ -59,10 +59,10 @@ export class OktaAuthProvider implements OAuthProviderHandlers { * allowing us to avoid using express-session in order to integrate with Okta. */ private _store: StateStore = { - store(req: Request, cb: any) { + store({}, cb: any) { cb(null, null); }, - verify(req: Request, state: string, cb: any) { + verify({}, {}, cb: any) { cb(null, true); }, }