diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index 0e01bf038c..bf91780c34 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -84,64 +84,6 @@ export interface Config { }; }; - /** - * The available auth-provider options and attributes - * @additionalProperties true - */ - providers?: { - /** @visibility frontend */ - saml?: { - entryPoint: string; - logoutUrl?: string; - issuer: string; - /** - * @visibility secret - */ - cert: string; - audience?: string; - /** - * @visibility secret - */ - privateKey?: string; - authnContext?: string[]; - identifierFormat?: string; - /** - * @visibility secret - */ - decryptionPvk?: string; - signatureAlgorithm?: 'sha256' | 'sha512'; - digestAlgorithm?: string; - acceptedClockSkewMs?: number; - }; - /** @visibility frontend */ - auth0?: { - [authEnv: string]: { - clientId: string; - /** - * @visibility secret - */ - clientSecret: string; - domain: string; - callbackUrl?: string; - audience?: string; - connection?: string; - connectionScope?: string; - }; - }; - /** @visibility frontend */ - onelogin?: { - [authEnv: string]: { - clientId: string; - /** - * @visibility secret - */ - clientSecret: string; - issuer: string; - callbackUrl?: string; - }; - }; - }; - /** * The backstage token expiration. */ diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 84441992e3..3040d03516 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -49,23 +49,6 @@ "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", - "@backstage/plugin-auth-backend-module-atlassian-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-auth0-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-aws-alb-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-bitbucket-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-gcp-iap-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-github-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-gitlab-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-google-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-microsoft-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-oauth2-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-oidc-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-okta-provider": "workspace:^", - "@backstage/plugin-auth-backend-module-onelogin-provider": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/types": "workspace:^", diff --git a/plugins/auth-backend/src/authPlugin.ts b/plugins/auth-backend/src/authPlugin.ts index 89b7e9a780..bc02243446 100644 --- a/plugins/auth-backend/src/authPlugin.ts +++ b/plugins/auth-backend/src/authPlugin.ts @@ -88,7 +88,6 @@ export const authPlugin = createBackendPlugin({ httpAuth, catalogApi, providerFactories: Object.fromEntries(providers), - disableDefaultProviderFactories: true, ownershipResolver, }); httpRouter.addAuthPolicy({ diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts deleted file mode 100644 index 48163e6e82..0000000000 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express from 'express'; -import { THOUSAND_DAYS_MS, TEN_MINUTES_MS, OAuthAdapter } from './OAuthAdapter'; -import { encodeState } from './helpers'; -import { OAuthHandlers, OAuthLogoutRequest } from './types'; -import { CookieConfigurer, OAuthState } from '@backstage/plugin-auth-node'; - -const mockResponseData = { - providerInfo: { - accessToken: 'ACCESS_TOKEN', - token: 'ID_TOKEN', - expiresInSeconds: 10, - scope: 'email', - }, - profile: { - email: 'foo@bar.com', - }, - backstageIdentity: { - token: - 'eyblob.eyJzdWIiOiJ1c2VyOmRlZmF1bHQvamltbXltYXJrdW0iLCJlbnQiOlsidXNlcjpkZWZhdWx0L2ppbW15bWFya3VtIl19.eyblob', - }, -}; - -describe('OAuthAdapter', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - class MyAuthProvider implements OAuthHandlers { - async start() { - return { - url: '/url', - status: 301, - }; - } - async handler() { - return { - response: mockResponseData, - refreshToken: 'token', - }; - } - async refresh() { - return { - response: mockResponseData, - refreshToken: 'token', - }; - } - async logout(_: OAuthLogoutRequest) {} - } - const providerInstance = new MyAuthProvider(); - const mockCookieConfig: ReturnType = { - domain: 'domain.org', - path: '/auth/test-provider', - secure: false, - }; - const mockCookieConfigurer = jest.fn().mockReturnValue(mockCookieConfig); - - const oAuthProviderOptions = { - providerId: 'test-provider', - appOrigin: 'http://localhost:3000', - baseUrl: 'http://domain.org/auth', - cookieConfigurer: mockCookieConfigurer, - tokenIssuer: { - issueToken: async () => 'my-id-token', - listPublicKeys: async () => ({ keys: [] }), - }, - isOriginAllowed: () => false, - callbackUrl: 'http://domain.org/auth/test-provider/handler/frame', - }; - - const defaultState = { nonce: 'nonce', env: 'development' }; - - const createEncodedQueryMockRequest = (state: any) => { - return { - cookies: { - 'test-provider-nonce': 'nonce', - }, - query: { - state: encodeState(state), - }, - } as unknown as express.Request; - }; - - const mockResponse = { - cookie: jest.fn().mockReturnThis(), - end: jest.fn().mockReturnThis(), - setHeader: jest.fn().mockReturnThis(), - statusCode: jest.fn().mockReturnThis(), - redirect: jest.fn().mockReturnThis(), - status: jest.fn().mockReturnThis(), - json: jest.fn().mockReturnThis(), - } as unknown as express.Response; - - const mockStartRequest = { - query: { - scope: 'user', - env: 'development', - }, - } as unknown as express.Request; - - const expectedStartAuthCookieData = { - httpOnly: true, - path: '/auth/test-provider/handler', - maxAge: TEN_MINUTES_MS, - domain: 'domain.org', - sameSite: 'lax', - secure: false, - }; - - it('sets the correct headers in start', async () => { - const oauthProvider = new OAuthAdapter( - providerInstance, - oAuthProviderOptions, - ); - - await oauthProvider.start(mockStartRequest, mockResponse); - // nonce cookie checks - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - `${oAuthProviderOptions.providerId}-nonce`, - expect.any(String), - expect.objectContaining(expectedStartAuthCookieData), - ); - expect(mockResponse.setHeader).toHaveBeenCalledTimes(2); - expect(mockResponse.setHeader).toHaveBeenCalledWith('Location', '/url'); - expect(mockResponse.setHeader).toHaveBeenCalledWith('Content-Length', '0'); - expect(mockResponse.statusCode).toEqual(301); - expect(mockResponse.end).toHaveBeenCalledTimes(1); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - const refreshCookieData = { - ...expectedStartAuthCookieData, - path: '/auth/test-provider', - maxAge: THOUSAND_DAYS_MS, - }; - - it('sets the refresh cookie if refresh is enabled', async () => { - const oauthProvider = new OAuthAdapter(providerInstance, { - ...oAuthProviderOptions, - isOriginAllowed: () => false, - }); - - const mockRequest = createEncodedQueryMockRequest(defaultState); - - await oauthProvider.frameHandler(mockRequest, mockResponse); - expect(mockCookieConfigurer).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - expect.stringContaining('test-provider-refresh-token'), - expect.stringContaining('token'), - expect.objectContaining(refreshCookieData), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - it('sets the refresh cookie if refresh is enabled with redirect', async () => { - const oauthProvider = new OAuthAdapter(providerInstance, { - ...oAuthProviderOptions, - isOriginAllowed: () => false, - }); - - const state = { - ...defaultState, - redirectUrl: 'http://localhost:3000', - flow: 'redirect', - }; - const mockRequest = createEncodedQueryMockRequest(state); - - await oauthProvider.frameHandler(mockRequest, mockResponse); - expect(mockResponse.redirect).toHaveBeenCalledTimes(1); - }); - - it('persists scope through cookie if enabled', async () => { - const handlers = { - start: jest.fn(async (_req: { state: OAuthState }) => ({ - url: '/url', - status: 301, - })), - handler: jest.fn(async () => ({ response: mockResponseData })), - refresh: jest.fn(async () => ({ response: mockResponseData })), - }; - const oauthProvider = new OAuthAdapter(handlers, { - ...oAuthProviderOptions, - persistScopes: true, - }); - - // First we test the /start request, making sure state is set - await oauthProvider.start(mockStartRequest, mockResponse); - - expect(handlers.start).toHaveBeenCalledTimes(1); - expect(handlers.start).toHaveBeenCalledWith({ - ...mockStartRequest, - scope: 'user', - state: { - nonce: expect.any(String), - env: 'development', - scope: 'user', - }, - }); - - // Then test the /handler, making sure the granted scope cookie is set - const providedState = handlers.start.mock.calls[0][0].state; - const mockHandleReq = { - cookies: { - 'test-provider-nonce': providedState.nonce, - }, - query: { - state: encodeState(providedState), - }, - } as unknown as express.Request; - const mockHandleRes = { - cookie: jest.fn().mockReturnThis(), - setHeader: jest.fn().mockReturnThis(), - end: jest.fn().mockReturnThis(), - redirect: jest.fn().mockReturnThis(), - } as unknown as express.Response; - - await oauthProvider.frameHandler(mockHandleReq, mockHandleRes); - expect(mockHandleRes.cookie).toHaveBeenCalledTimes(1); - expect(mockHandleRes.cookie).toHaveBeenCalledWith( - 'test-provider-granted-scope', - 'user', - expect.objectContaining(refreshCookieData), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - - // Then make sure scopes are forwarded correctly during refresh - const mockRefreshReq = { - query: { scope: 'ignore-me' }, - cookies: { - 'test-provider-granted-scope': 'user', - 'test-provider-refresh-token': 'refresh-token', - }, - header: jest.fn().mockReturnValue('XMLHttpRequest'), - } as unknown as express.Request; - const mockRefreshRes = { - status: jest.fn().mockReturnThis(), - json: jest.fn().mockReturnThis(), - redirect: jest.fn().mockReturnThis(), - } as unknown as express.Response; - await oauthProvider.refresh(mockRefreshReq, mockRefreshRes); - expect(handlers.refresh).toHaveBeenCalledTimes(1); - expect(handlers.refresh).toHaveBeenCalledWith( - expect.objectContaining({ - scope: 'user', - refreshToken: 'refresh-token', - }), - ); - expect(mockRefreshRes.redirect).not.toHaveBeenCalled(); - }); - - const mockRequestWithHeader = { - header: () => 'XMLHttpRequest', - cookies: { - 'test-provider-refresh-token': 'token', - }, - query: {}, - get: jest.fn(), - } as unknown as express.Request; - - it('removes refresh cookie and calls logout handler when logging out', async () => { - const logoutSpy = jest.spyOn(providerInstance, 'logout'); - const oauthProvider = new OAuthAdapter(providerInstance, { - ...oAuthProviderOptions, - isOriginAllowed: () => false, - }); - - await oauthProvider.logout(mockRequestWithHeader, mockResponse); - expect(mockRequestWithHeader.get).toHaveBeenCalledTimes(1); - expect(logoutSpy).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - expect.stringContaining('test-provider-refresh-token'), - '', - expect.objectContaining({ path: '/auth/test-provider' }), - ); - expect(mockResponse.end).toHaveBeenCalledTimes(1); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - it('gets new access-token when refreshing', async () => { - const oauthProvider = new OAuthAdapter(providerInstance, { - ...oAuthProviderOptions, - isOriginAllowed: () => false, - }); - - await oauthProvider.refresh(mockRequestWithHeader, mockResponse); - expect(mockResponse.json).toHaveBeenCalledTimes(1); - expect(mockResponse.json).toHaveBeenCalledWith({ - ...mockResponseData, - backstageIdentity: { - token: mockResponseData.backstageIdentity.token, - identity: { - type: 'user', - userEntityRef: 'user:default/jimmymarkum', - ownershipEntityRefs: ['user:default/jimmymarkum'], - }, - }, - }); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - it('sets new access-token when old cookie exists', async () => { - const oauthProvider = new OAuthAdapter(providerInstance, { - ...oAuthProviderOptions, - isOriginAllowed: () => false, - }); - - const mockRequest = { - ...mockRequestWithHeader, - cookies: { - 'test-provider-refresh-token': 'old-token', - }, - } as unknown as express.Request; - - await oauthProvider.refresh(mockRequest, mockResponse); - expect(mockRequest.get).toHaveBeenCalledTimes(1); - expect(mockCookieConfigurer).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - 'test-provider-refresh-token', - 'token', - expect.objectContaining(refreshCookieData), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - it('sets the correct nonce cookie configuration', async () => { - const config = { - baseUrl: 'http://domain.org/auth', - appUrl: 'http://domain.org', - isOriginAllowed: () => false, - }; - - const oauthProvider = OAuthAdapter.fromConfig(config, providerInstance, { - ...oAuthProviderOptions, - }); - - await oauthProvider.start(mockStartRequest, mockResponse); - expect(mockCookieConfigurer).not.toHaveBeenCalled(); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - `${oAuthProviderOptions.providerId}-nonce`, - expect.any(String), - expect.objectContaining(expectedStartAuthCookieData), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - const config = { - baseUrl: 'http://domain.org/auth', - appUrl: 'http://domain.org', - isOriginAllowed: () => false, - }; - - const mockStartRequestWithOrigin = { - query: { - scope: 'user', - env: 'development', - origin: 'http://other.domain', - }, - } as unknown as express.Request; - - it('sets the correct nonce cookie configuration using origin from request', async () => { - const oauthProvider = OAuthAdapter.fromConfig(config, providerInstance, { - ...oAuthProviderOptions, - callbackUrl: 'https://domain.org/auth/test-provider/handler/frame', - }); - - await oauthProvider.start(mockStartRequestWithOrigin, mockResponse); - expect(mockCookieConfigurer).not.toHaveBeenCalled(); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - `${oAuthProviderOptions.providerId}-nonce`, - expect.any(String), - expect.objectContaining({ - ...expectedStartAuthCookieData, - secure: true, - sameSite: 'none', - }), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - const secureCookieData = { - ...refreshCookieData, - secure: true, - sameSite: 'lax', - maxAge: THOUSAND_DAYS_MS, - }; - - it('sets the correct cookie configuration using an secure callbackUrl', async () => { - const oauthProvider = OAuthAdapter.fromConfig(config, providerInstance, { - ...oAuthProviderOptions, - callbackUrl: 'https://domain.org/auth/test-provider/handler/frame', - }); - - const mockRequest = createEncodedQueryMockRequest(defaultState); - await oauthProvider.frameHandler(mockRequest, mockResponse); - expect(mockCookieConfigurer).not.toHaveBeenCalled(); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - expect.stringContaining('test-provider-refresh-token'), - expect.stringContaining('token'), - expect.objectContaining(secureCookieData), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - const secureSameSiteNoneCookieData = { - ...secureCookieData, - sameSite: 'none', - }; - - it('sets the correct cookie configuration when on different domains and secure', async () => { - const oauthProvider = OAuthAdapter.fromConfig(config, providerInstance, { - ...oAuthProviderOptions, - callbackUrl: 'https://authdomain.org/auth/test-provider/handler/frame', - }); - - const mockRequest = createEncodedQueryMockRequest(defaultState); - await oauthProvider.frameHandler(mockRequest, mockResponse); - expect(mockCookieConfigurer).not.toHaveBeenCalled(); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - expect.stringContaining('test-provider-refresh-token'), - expect.stringContaining('token'), - expect.objectContaining({ - ...secureSameSiteNoneCookieData, - domain: 'authdomain.org', - }), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - const configOriginAllowed = { - ...config, - isOriginAllowed: () => true, - }; - - it('sets the correct cookie configuration using origin from state', async () => { - const oauthProvider = OAuthAdapter.fromConfig( - configOriginAllowed, - providerInstance, - { - ...oAuthProviderOptions, - callbackUrl: 'https://domain.org/auth/test-provider/handler/frame', - }, - ); - - const mockRequest = createEncodedQueryMockRequest({ - ...defaultState, - origin: 'http://other.domain', - }); - await oauthProvider.frameHandler(mockRequest, mockResponse); - expect(mockCookieConfigurer).not.toHaveBeenCalled(); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - expect.stringContaining('test-provider-refresh-token'), - expect.stringContaining('token'), - expect.objectContaining(secureSameSiteNoneCookieData), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - const mockRequestWithGetMockReturn = { - header: () => 'XMLHttpRequest', - cookies: { - 'test-provider-refresh-token': 'old-token', - }, - query: {}, - get: jest.fn().mockReturnValue('http://other.domain'), - } as unknown as express.Request; - - it('sets the correct cookie configuration using origin from header', async () => { - const oauthProvider = OAuthAdapter.fromConfig(config, providerInstance, { - ...oAuthProviderOptions, - callbackUrl: 'https://domain.org/auth/test-provider/handler/frame', - }); - - await oauthProvider.refresh(mockRequestWithGetMockReturn, mockResponse); - expect(mockRequestWithGetMockReturn.get).toHaveBeenCalledTimes(1); - expect(mockCookieConfigurer).not.toHaveBeenCalled(); - expect(mockResponse.cookie).toHaveBeenCalledTimes(1); - expect(mockResponse.cookie).toHaveBeenCalledWith( - 'test-provider-refresh-token', - 'token', - expect.objectContaining(secureSameSiteNoneCookieData), - ); - expect(mockResponse.redirect).not.toHaveBeenCalled(); - }); - - it('executed a response redirect when flow query string is set to "redirect"', async () => { - const handlers = { - start: jest.fn(async (_req: { state: OAuthState }) => ({ - url: '/url', - status: 301, - })), - handler: jest.fn(async () => ({ response: mockResponseData })), - refresh: jest.fn(async () => ({ response: mockResponseData })), - }; - const configWithNoPopupEnabled = { - ...configOriginAllowed, - }; - const oauthProvider = OAuthAdapter.fromConfig( - configWithNoPopupEnabled, - handlers, - { - ...oAuthProviderOptions, - callbackUrl: 'https://domain.org/auth/test-provider/handler/frame', - }, - ); - - const state = { - ...defaultState, - origin: 'http://other.domain', - redirectUrl: 'http://domain.org', - flow: 'redirect', - }; - - const mockRequest = { - ...createEncodedQueryMockRequest(state), - get: jest.fn().mockReturnValue('http://other.domain'), - } as unknown as express.Request; - - await oauthProvider.frameHandler(mockRequest, mockResponse); - expect(mockRequest.get).not.toHaveBeenCalled(); - expect(mockCookieConfigurer).not.toHaveBeenCalled(); - expect(mockResponse.cookie).not.toHaveBeenCalled(); - expect(mockResponse.redirect).toHaveBeenCalledTimes(1); - expect(mockResponse.redirect).toHaveBeenCalledWith('http://domain.org'); - }); -}); diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts deleted file mode 100644 index b5c3642024..0000000000 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express, { CookieOptions } from 'express'; -import crypto from 'crypto'; -import { URL } from 'url'; -import { - AuthProviderConfig, - AuthProviderRouteHandlers, - BackstageIdentityResponse, - BackstageSignInResult, - CookieConfigurer, - OAuthState, -} from '@backstage/plugin-auth-node'; -import { - AuthenticationError, - InputError, - isError, - NotAllowedError, -} from '@backstage/errors'; -import { defaultCookieConfigurer, readState, verifyNonce } from './helpers'; -import { - postMessageResponse, - ensuresXRequestedWith, - WebMessageResponse, -} from '../flow'; -import { - OAuthHandlers, - OAuthStartRequest, - OAuthRefreshRequest, - OAuthLogoutRequest, -} from './types'; -import { prepareBackstageIdentityResponse } from '../../providers/prepareBackstageIdentityResponse'; - -export const THOUSAND_DAYS_MS = 1000 * 24 * 60 * 60 * 1000; -export const TEN_MINUTES_MS = 600 * 1000; - -/** - * @public - * @deprecated Use `createOAuthRouteHandlers` from `@backstage/plugin-auth-node` instead - */ -export type OAuthAdapterOptions = { - providerId: string; - persistScopes?: boolean; - appOrigin: string; - baseUrl: string; - cookieConfigurer: CookieConfigurer; - isOriginAllowed: (origin: string) => boolean; - callbackUrl: string; -}; - -/** - * @public - * @deprecated Use `createOAuthRouteHandlers` from `@backstage/plugin-auth-node` instead - */ -export class OAuthAdapter implements AuthProviderRouteHandlers { - static fromConfig( - config: AuthProviderConfig, - handlers: OAuthHandlers, - options: Pick< - OAuthAdapterOptions, - 'providerId' | 'persistScopes' | 'callbackUrl' - >, - ): OAuthAdapter { - const { appUrl, baseUrl, isOriginAllowed } = config; - const { origin: appOrigin } = new URL(appUrl); - - const cookieConfigurer = config.cookieConfigurer ?? defaultCookieConfigurer; - - return new OAuthAdapter(handlers, { - ...options, - appOrigin, - baseUrl, - cookieConfigurer, - isOriginAllowed, - }); - } - - private readonly baseCookieOptions: CookieOptions; - - constructor( - private readonly handlers: OAuthHandlers, - private readonly options: OAuthAdapterOptions, - ) { - this.baseCookieOptions = { - httpOnly: true, - sameSite: 'lax', - }; - } - - async start(req: express.Request, res: express.Response): Promise { - // retrieve scopes from request - const scope = req.query.scope?.toString() ?? ''; - const env = req.query.env?.toString(); - const origin = req.query.origin?.toString(); - const redirectUrl = req.query.redirectUrl?.toString(); - const flow = req.query.flow?.toString(); - - if (!env) { - throw new InputError('No env provided in request query parameters'); - } - - const cookieConfig = this.getCookieConfig(origin); - - const nonce = crypto.randomBytes(16).toString('base64'); - // set a nonce cookie before redirecting to oauth provider - this.setNonceCookie(res, nonce, cookieConfig); - - const state: OAuthState = { nonce, env, origin, redirectUrl, flow }; - - // If scopes are persisted then we pass them through the state so that we - // can set the cookie on successful auth - if (this.options.persistScopes) { - state.scope = scope; - } - const forwardReq = Object.assign(req, { scope, state }); - - const { url, status } = await this.handlers.start( - forwardReq as OAuthStartRequest, - ); - - res.statusCode = status || 302; - res.setHeader('Location', url); - res.setHeader('Content-Length', '0'); - res.end(); - } - - async frameHandler( - req: express.Request, - res: express.Response, - ): Promise { - let appOrigin = this.options.appOrigin; - - try { - const state: OAuthState = readState(req.query.state?.toString() ?? ''); - - if (state.origin) { - try { - appOrigin = new URL(state.origin).origin; - } catch { - throw new NotAllowedError('App origin is invalid, failed to parse'); - } - if (!this.options.isOriginAllowed(appOrigin)) { - throw new NotAllowedError(`Origin '${appOrigin}' is not allowed`); - } - } - - // verify nonce cookie and state cookie on callback - verifyNonce(req, this.options.providerId); - - const { response, refreshToken } = await this.handlers.handler(req); - - const cookieConfig = this.getCookieConfig(appOrigin); - - // Store the scope that we have been granted for this session. This is useful if - // the provider does not return granted scopes on refresh or if they are normalized. - if (this.options.persistScopes && state.scope) { - this.setGrantedScopeCookie(res, state.scope, cookieConfig); - response.providerInfo.scope = state.scope; - } - - if (refreshToken) { - // set new refresh token - this.setRefreshTokenCookie(res, refreshToken, cookieConfig); - } - - const identity = await this.populateIdentity(response.backstageIdentity); - - const responseObj: WebMessageResponse = { - type: 'authorization_response', - response: { ...response, backstageIdentity: identity }, - }; - - if (state.flow === 'redirect') { - if (!state.redirectUrl) { - throw new InputError( - 'No redirectUrl provided in request query parameters', - ); - } - res.redirect(state.redirectUrl); - return undefined; - } - // post message back to popup if successful - return postMessageResponse(res, appOrigin, responseObj); - } catch (error) { - const { name, message } = isError(error) - ? error - : new Error('Encountered invalid error'); // Being a bit safe and not forwarding the bad value - // post error message back to popup if failure - return postMessageResponse(res, appOrigin, { - type: 'authorization_response', - error: { name, message }, - }); - } - } - - async logout(req: express.Request, res: express.Response): Promise { - if (!ensuresXRequestedWith(req)) { - throw new AuthenticationError('Invalid X-Requested-With header'); - } - - if (this.handlers.logout) { - const refreshToken = this.getRefreshTokenFromCookie(req); - const revokeRequest: OAuthLogoutRequest = Object.assign(req, { - refreshToken, - }); - await this.handlers.logout(revokeRequest); - } - - // remove refresh token cookie if it is set - const origin = req.get('origin'); - const cookieConfig = this.getCookieConfig(origin); - this.removeRefreshTokenCookie(res, cookieConfig); - - res.status(200).end(); - } - - async refresh(req: express.Request, res: express.Response): Promise { - if (!ensuresXRequestedWith(req)) { - throw new AuthenticationError('Invalid X-Requested-With header'); - } - - if (!this.handlers.refresh) { - throw new InputError( - `Refresh token is not supported for provider ${this.options.providerId}`, - ); - } - - try { - const refreshToken = this.getRefreshTokenFromCookie(req); - - // throw error if refresh token is missing in the request - if (!refreshToken) { - throw new InputError('Missing session cookie'); - } - - let scope = req.query.scope?.toString() ?? ''; - if (this.options.persistScopes) { - scope = this.getGrantedScopeFromCookie(req); - } - const forwardReq = Object.assign(req, { scope, refreshToken }); - - // get new access_token - const { response, refreshToken: newRefreshToken } = - await this.handlers.refresh(forwardReq as OAuthRefreshRequest); - - const backstageIdentity = await this.populateIdentity( - response.backstageIdentity, - ); - - if (newRefreshToken && newRefreshToken !== refreshToken) { - const origin = req.get('origin'); - const cookieConfig = this.getCookieConfig(origin); - this.setRefreshTokenCookie(res, newRefreshToken, cookieConfig); - } - - res.status(200).json({ ...response, backstageIdentity }); - } catch (error) { - throw new AuthenticationError('Refresh failed', error); - } - } - - /** - * If the response from the OAuth provider includes a Backstage identity, we - * make sure it's populated with all the information we can derive from the user ID. - */ - private async populateIdentity( - identity?: BackstageSignInResult, - ): Promise { - if (!identity) { - return undefined; - } - if (!identity.token) { - throw new InputError(`Identity response must return a token`); - } - - return prepareBackstageIdentityResponse(identity); - } - - private setNonceCookie = ( - res: express.Response, - nonce: string, - cookieConfig: ReturnType, - ) => { - res.cookie(`${this.options.providerId}-nonce`, nonce, { - maxAge: TEN_MINUTES_MS, - ...this.baseCookieOptions, - ...cookieConfig, - path: `${cookieConfig.path}/handler`, - }); - }; - - private setGrantedScopeCookie = ( - res: express.Response, - scope: string, - cookieConfig: ReturnType, - ) => { - res.cookie(`${this.options.providerId}-granted-scope`, scope, { - maxAge: THOUSAND_DAYS_MS, - ...this.baseCookieOptions, - ...cookieConfig, - }); - }; - - private getRefreshTokenFromCookie = (req: express.Request) => { - return req.cookies[`${this.options.providerId}-refresh-token`]; - }; - - private getGrantedScopeFromCookie = (req: express.Request) => { - return req.cookies[`${this.options.providerId}-granted-scope`]; - }; - - private setRefreshTokenCookie = ( - res: express.Response, - refreshToken: string, - cookieConfig: ReturnType, - ) => { - res.cookie(`${this.options.providerId}-refresh-token`, refreshToken, { - maxAge: THOUSAND_DAYS_MS, - ...this.baseCookieOptions, - ...cookieConfig, - }); - }; - - private removeRefreshTokenCookie = ( - res: express.Response, - cookieConfig: ReturnType, - ) => { - res.cookie(`${this.options.providerId}-refresh-token`, '', { - maxAge: 0, - ...this.baseCookieOptions, - ...cookieConfig, - }); - }; - - private getCookieConfig = (origin?: string) => { - return this.options.cookieConfigurer({ - providerId: this.options.providerId, - baseUrl: this.options.baseUrl, - callbackUrl: this.options.callbackUrl, - appOrigin: origin ?? this.options.appOrigin, - }); - }; -} diff --git a/plugins/auth-backend/src/lib/oauth/index.ts b/plugins/auth-backend/src/lib/oauth/index.ts index 3643898bed..f3416b6236 100644 --- a/plugins/auth-backend/src/lib/oauth/index.ts +++ b/plugins/auth-backend/src/lib/oauth/index.ts @@ -15,8 +15,6 @@ */ export { OAuthEnvironmentHandler } from './OAuthEnvironmentHandler'; -export type { OAuthAdapterOptions } from './OAuthAdapter'; -export { OAuthAdapter } from './OAuthAdapter'; export { encodeState, verifyNonce, readState } from './helpers'; export type { OAuthHandlers, diff --git a/plugins/auth-backend/src/providers/atlassian/index.ts b/plugins/auth-backend/src/providers/atlassian/index.ts deleted file mode 100644 index f001463694..0000000000 --- a/plugins/auth-backend/src/providers/atlassian/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { atlassian } from './provider'; diff --git a/plugins/auth-backend/src/providers/atlassian/provider.ts b/plugins/auth-backend/src/providers/atlassian/provider.ts deleted file mode 100644 index 539f055f75..0000000000 --- a/plugins/auth-backend/src/providers/atlassian/provider.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { atlassianAuthenticator } from '@backstage/plugin-auth-backend-module-atlassian-provider'; -import { - SignInResolver, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, -} from '../../lib/legacy'; -import { OAuthResult } from '../../lib/oauth'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { AuthHandler } from '../types'; - -/** - * Auth provider integration for Atlassian auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const atlassian = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: atlassianAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/atlassian/strategy.ts b/plugins/auth-backend/src/providers/atlassian/strategy.ts deleted file mode 100644 index d07b09c5f8..0000000000 --- a/plugins/auth-backend/src/providers/atlassian/strategy.ts +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import OAuth2Strategy, { InternalOAuthError } from 'passport-oauth2'; -import { Profile } from 'passport'; - -interface ProfileResponse { - account_id: string; - email: string; - name: string; - picture: string; - nickname: string; -} - -interface AtlassianStrategyOptions { - clientID: string; - clientSecret: string; - callbackURL: string; - scope: string; -} - -const defaultScopes = ['offline_access', 'read:me']; - -export default class AtlassianStrategy extends OAuth2Strategy { - private readonly profileURL: string; - - constructor( - options: AtlassianStrategyOptions, - verify: OAuth2Strategy.VerifyFunction, - ) { - if (!options.scope) { - throw new TypeError('Atlassian requires a scope option'); - } - - const scopes = options.scope.split(' '); - - const optionsWithURLs = { - ...options, - authorizationURL: `https://auth.atlassian.com/authorize`, - tokenURL: `https://auth.atlassian.com/oauth/token`, - scope: Array.from(new Set([...defaultScopes, ...scopes])), - }; - - super(optionsWithURLs, verify); - this.profileURL = 'https://api.atlassian.com/me'; - this.name = 'atlassian'; - - this._oauth2.useAuthorizationHeaderforGET(true); - } - - authorizationParams() { - return { - audience: 'api.atlassian.com', - prompt: 'consent', - }; - } - - userProfile( - accessToken: string, - done: (err?: Error | null, profile?: any) => void, - ): void { - this._oauth2.get(this.profileURL, accessToken, (err, body) => { - if (err) { - return done( - new InternalOAuthError( - 'Failed to fetch user profile', - err.statusCode, - ), - ); - } - - if (!body) { - return done( - new Error('Failed to fetch user profile, body cannot be empty'), - ); - } - - try { - const json = typeof body !== 'string' ? body.toString() : body; - const profile = AtlassianStrategy.parse(json); - return done(null, profile); - } catch (e) { - return done(new Error('Failed to parse user profile')); - } - }); - } - - static parse(json: string): Profile { - const resp = JSON.parse(json) as ProfileResponse; - - return { - id: resp.account_id, - provider: 'atlassian', - username: resp.nickname, - displayName: resp.name, - emails: [{ value: resp.email }], - photos: [{ value: resp.picture }], - }; - } -} diff --git a/plugins/auth-backend/src/providers/auth0/index.ts b/plugins/auth-backend/src/providers/auth0/index.ts deleted file mode 100644 index 94a08a5809..0000000000 --- a/plugins/auth-backend/src/providers/auth0/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { auth0 } from './provider'; diff --git a/plugins/auth-backend/src/providers/auth0/provider.ts b/plugins/auth-backend/src/providers/auth0/provider.ts deleted file mode 100644 index 9ae31b305d..0000000000 --- a/plugins/auth-backend/src/providers/auth0/provider.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { OAuthProviderOptions, OAuthResult } from '../../lib/oauth'; - -import { AuthHandler } from '../types'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - AuthResolverContext, - createOAuthProviderFactory, - SignInResolver, -} from '@backstage/plugin-auth-node'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, -} from '../../lib/legacy'; -import { auth0Authenticator } from '@backstage/plugin-auth-backend-module-auth0-provider'; - -/** - * @public - * @deprecated The Auth0 auth provider was extracted to `@backstage/plugin-auth-backend-module-auth0-provider`. - */ -export type Auth0AuthProviderOptions = OAuthProviderOptions & { - domain: string; - signInResolver?: SignInResolver; - authHandler: AuthHandler; - resolverContext: AuthResolverContext; - audience?: string; - connection?: string; - connectionScope?: string; -}; - -/** - * Auth provider integration for auth0 auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const auth0 = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: auth0Authenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/auth0/strategy.ts b/plugins/auth-backend/src/providers/auth0/strategy.ts deleted file mode 100644 index cf5b522ec5..0000000000 --- a/plugins/auth-backend/src/providers/auth0/strategy.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import Auth0InternalStrategy from 'passport-auth0'; -import { StateStore } from 'passport-oauth2'; - -export interface Auth0StrategyOptionsWithRequest { - clientID: string; - clientSecret: string; - callbackURL: string; - domain: string; - passReqToCallback: true; - store: StateStore; -} - -export default class Auth0Strategy extends Auth0InternalStrategy { - constructor( - options: Auth0StrategyOptionsWithRequest, - verify: Auth0InternalStrategy.VerifyFunction, - ) { - const optionsWithURLs = { - ...options, - authorizationURL: `https://${options.domain}/authorize`, - tokenURL: `https://${options.domain}/oauth/token`, - userInfoURL: `https://${options.domain}/userinfo`, - apiUrl: `https://${options.domain}/api`, - }; - super(optionsWithURLs, verify); - } -} diff --git a/plugins/auth-backend/src/providers/aws-alb/index.ts b/plugins/auth-backend/src/providers/aws-alb/index.ts deleted file mode 100644 index 6784888b1f..0000000000 --- a/plugins/auth-backend/src/providers/aws-alb/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { awsAlb } from './provider'; -export type { AwsAlbResult } from './types'; diff --git a/plugins/auth-backend/src/providers/aws-alb/provider.ts b/plugins/auth-backend/src/providers/aws-alb/provider.ts deleted file mode 100644 index 18d4f42f32..0000000000 --- a/plugins/auth-backend/src/providers/aws-alb/provider.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - AwsAlbResult, - awsAlbAuthenticator, -} from '@backstage/plugin-auth-backend-module-aws-alb-provider'; -import { - SignInResolver, - createProxyAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { AuthHandler } from '../types'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; - -/** - * Auth provider integration for AWS ALB auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const awsAlb = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth - * response into the profile that will be presented to the user. The default - * implementation just provides the authenticated email that the IAP - * presented. - */ - authHandler?: AuthHandler; - /** - * Configures sign-in for this provider. - */ - signIn: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return createProxyAuthProviderFactory({ - authenticator: awsAlbAuthenticator, - profileTransform: options?.authHandler, - signInResolver: options?.signIn?.resolver, - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/aws-alb/types.ts b/plugins/auth-backend/src/providers/aws-alb/types.ts deleted file mode 100644 index 2640a4a7be..0000000000 --- a/plugins/auth-backend/src/providers/aws-alb/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AwsAlbResult as _AwsAlbResult } from '@backstage/plugin-auth-backend-module-aws-alb-provider'; - -/** - * The result of the initial auth challenge. This is the input to the auth - * callbacks. - * - * @public - * @deprecated import from `@backstage/plugin-auth-backend-module-aws-alb-provider` instead - */ -export type AwsAlbResult = _AwsAlbResult; diff --git a/plugins/auth-backend/src/providers/azure-easyauth/index.ts b/plugins/auth-backend/src/providers/azure-easyauth/index.ts deleted file mode 100644 index de50e32745..0000000000 --- a/plugins/auth-backend/src/providers/azure-easyauth/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { easyAuth } from './provider'; -import { AzureEasyAuthResult } from '@backstage/plugin-auth-backend-module-azure-easyauth-provider'; - -/** - * @public - * @deprecated import AzureEasyAuthResult from `@backstage/plugin-auth-backend-module-azure-easyauth-provider` instead - */ -export type EasyAuthResult = AzureEasyAuthResult; diff --git a/plugins/auth-backend/src/providers/azure-easyauth/provider.ts b/plugins/auth-backend/src/providers/azure-easyauth/provider.ts deleted file mode 100644 index 202f99a7e1..0000000000 --- a/plugins/auth-backend/src/providers/azure-easyauth/provider.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - SignInResolver, - createProxyAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { AuthHandler } from '../types'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - AzureEasyAuthResult, - azureEasyAuthAuthenticator, -} from '@backstage/plugin-auth-backend-module-azure-easyauth-provider'; - -/** - * Auth provider integration for Azure EasyAuth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const easyAuth = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return createProxyAuthProviderFactory({ - authenticator: azureEasyAuthAuthenticator, - profileTransform: options?.authHandler, - signInResolver: options?.signIn?.resolver, - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/bitbucket/index.ts b/plugins/auth-backend/src/providers/bitbucket/index.ts deleted file mode 100644 index 9d82c1066c..0000000000 --- a/plugins/auth-backend/src/providers/bitbucket/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { bitbucket } from './provider'; -export type { - BitbucketPassportProfile, - BitbucketOAuthResult, -} from './provider'; diff --git a/plugins/auth-backend/src/providers/bitbucket/provider.ts b/plugins/auth-backend/src/providers/bitbucket/provider.ts deleted file mode 100644 index 69ac2cf23b..0000000000 --- a/plugins/auth-backend/src/providers/bitbucket/provider.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - bitbucketAuthenticator, - bitbucketSignInResolvers, -} from '@backstage/plugin-auth-backend-module-bitbucket-provider'; -import { - SignInResolver, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { Profile as PassportProfile } from 'passport'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, - adaptOAuthSignInResolverToLegacy, -} from '../../lib/legacy'; -import { OAuthResult } from '../../lib/oauth'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { AuthHandler } from '../types'; - -/** - * @public - * @deprecated The Bitbucket auth provider was extracted to `@backstage/plugin-auth-backend-module-bitbucket-provider`. - */ -export type BitbucketOAuthResult = { - fullProfile: BitbucketPassportProfile; - params: { - id_token?: string; - scope: string; - expires_in: number; - }; - accessToken: string; - refreshToken?: string; -}; - -/** - * @public - * @deprecated The Bitbucket auth provider was extracted to `@backstage/plugin-auth-backend-module-bitbucket-provider`. - */ -export type BitbucketPassportProfile = PassportProfile & { - id?: string; - displayName?: string; - username?: string; - avatarUrl?: string; - _json?: { - links?: { - avatar?: { - href?: string; - }; - }; - }; -}; - -/** - * Auth provider integration for Bitbucket auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const bitbucket = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: bitbucketAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, - resolvers: adaptOAuthSignInResolverToLegacy({ - userIdMatchingUserEntityAnnotation: - bitbucketSignInResolvers.userIdMatchingUserEntityAnnotation(), - usernameMatchingUserEntityAnnotation: - bitbucketSignInResolvers.usernameMatchingUserEntityAnnotation(), - }), -}); diff --git a/plugins/auth-backend/src/providers/bitbucketServer/index.ts b/plugins/auth-backend/src/providers/bitbucketServer/index.ts deleted file mode 100644 index cef12cd50d..0000000000 --- a/plugins/auth-backend/src/providers/bitbucketServer/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { bitbucketServer } from './provider'; -export type { BitbucketServerOAuthResult } from './provider'; diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts deleted file mode 100644 index c49cf5b7b1..0000000000 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Profile as PassportProfile } from 'passport'; -import { - AuthResolverContext, - createOAuthProviderFactory, - SignInResolver, -} from '@backstage/plugin-auth-node'; -import { - bitbucketServerAuthenticator, - bitbucketServerSignInResolvers, -} from '@backstage/plugin-auth-backend-module-bitbucket-server-provider'; -import { OAuthProviderOptions } from '../../lib/oauth'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, -} from '../../lib/legacy'; -import { AuthHandler } from '../types'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; - -/** - * @public - * @deprecated The Bitbucket Server auth provider was extracted to `@backstage/plugin-auth-backend-module-bitbucket-server-provider`. - */ -export type BitbucketServerOAuthResult = { - fullProfile: PassportProfile; - params: { - scope: string; - access_token?: string; - token_type?: string; - expires_in?: number; - }; - accessToken: string; - refreshToken?: string; -}; - -/** - * @public - * @deprecated The Bitbucket Server auth provider was extracted to `@backstage/plugin-auth-backend-module-bitbucket-server-provider`. - */ -export type BitbucketServerAuthProviderOptions = OAuthProviderOptions & { - host: string; - authorizationUrl: string; - tokenUrl: string; - authHandler: AuthHandler; - signInResolver?: SignInResolver; - resolverContext: AuthResolverContext; -}; - -export const bitbucketServer = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: bitbucketServerAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, - resolvers: { - /** - * Looks up the user by matching their email to the entity email. - */ - emailMatchingUserEntityProfileEmail: - (): SignInResolver => { - const resolver = - bitbucketServerSignInResolvers.emailMatchingUserEntityProfileEmail(); - return async (info, ctx) => { - return resolver( - { - profile: info.profile, - result: { - fullProfile: info.result.fullProfile, - session: { - accessToken: info.result.accessToken, - tokenType: info.result.params.token_type ?? 'bearer', - scope: info.result.params.scope, - expiresInSeconds: info.result.params.expires_in, - refreshToken: info.result.refreshToken, - }, - }, - }, - ctx, - ); - }; - }, - }, -}); diff --git a/plugins/auth-backend/src/providers/cloudflare-access/index.ts b/plugins/auth-backend/src/providers/cloudflare-access/index.ts deleted file mode 100644 index 19b56bd825..0000000000 --- a/plugins/auth-backend/src/providers/cloudflare-access/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { cfAccess } from './provider'; -export type { - CloudflareAccessClaims, - CloudflareAccessGroup, - CloudflareAccessResult, - CloudflareAccessIdentityProfile, -} from './provider'; diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts deleted file mode 100644 index 4710d60d47..0000000000 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - cloudflareAccessSignInResolvers, - createCloudflareAccessAuthenticator, -} from '@backstage/plugin-auth-backend-module-cloudflare-access-provider'; -import { - SignInResolver, - createProxyAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { AuthHandler } from '../types'; -import { CacheService } from '@backstage/backend-plugin-api'; - -/** - * CloudflareAccessClaims - * - * Can be used in externally provided auth handler or sign in resolver to - * enrich user profile for sign-in user entity - * - * @public - * @deprecated import from `@backstage/plugin-auth-backend-module-cloudflare-access-provider` instead - */ -export type CloudflareAccessClaims = { - /** - * `aud` identifies the application to which the JWT is issued. - */ - aud: string[]; - /** - * `email` contains the email address of the authenticated user. - */ - email: string; - /** - * iat and exp are the issuance and expiration timestamps. - */ - exp: number; - iat: number; - /** - * `nonce` is the session identifier. - */ - nonce: string; - /** - * `identity_nonce` is available in the Application Token and can be used to - * query all group membership for a given user. - */ - identity_nonce: string; - /** - * `sub` contains the identifier of the authenticated user. - */ - sub: string; - /** - * `iss` the issuer is the application’s Cloudflare Access Domain URL. - */ - iss: string; - /** - * `custom` contains SAML attributes in the Application Token specified by an - * administrator in the identity provider configuration. - */ - custom: string; -}; - -/** - * CloudflareAccessGroup - * - * @public - * @deprecated import from `@backstage/plugin-auth-backend-module-cloudflare-access-provider` instead - */ -export type CloudflareAccessGroup = { - /** - * Group id - */ - id: string; - /** - * Name of group as defined in Cloudflare zero trust dashboard - */ - name: string; - /** - * Access group email address - */ - email: string; -}; - -/** - * CloudflareAccessIdentityProfile - * - * Can be used in externally provided auth handler or sign in resolver to - * enrich user profile for sign-in user entity - * - * @public - * @deprecated import from `@backstage/plugin-auth-backend-module-cloudflare-access-provider` instead - */ -export type CloudflareAccessIdentityProfile = { - id: string; - name: string; - email: string; - groups: CloudflareAccessGroup[]; -}; - -/** - * @public - * @deprecated import from `@backstage/plugin-auth-backend-module-cloudflare-access-provider` instead - */ -export type CloudflareAccessResult = { - claims: CloudflareAccessClaims; - cfIdentity: CloudflareAccessIdentityProfile; - expiresInSeconds?: number; - token: string; -}; - -/** - * Auth provider integration for Cloudflare Access auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const cfAccess = createAuthProviderIntegration({ - create(options: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - - /** - * Cache service object that was configured for the Backstage backend, - * should be provided via the backend auth plugin. - */ - cache?: CacheService; - }) { - return createProxyAuthProviderFactory({ - authenticator: createCloudflareAccessAuthenticator({ - cache: options.cache, - }), - profileTransform: options?.authHandler, - signInResolver: options?.signIn?.resolver, - signInResolverFactories: cloudflareAccessSignInResolvers, - }); - }, - resolvers: cloudflareAccessSignInResolvers, -}); diff --git a/plugins/auth-backend/src/providers/createAuthProviderIntegration.ts b/plugins/auth-backend/src/providers/createAuthProviderIntegration.ts deleted file mode 100644 index 2f7bb4a4ec..0000000000 --- a/plugins/auth-backend/src/providers/createAuthProviderIntegration.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - AuthProviderFactory, - SignInResolver, -} from '@backstage/plugin-auth-node'; - -/** - * Creates a standardized representation of an integration with a third-party - * auth provider. - * - * The returned object facilitates the creation of provider instances, and - * supplies built-in sign-in resolvers for the specific provider. - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export function createAuthProviderIntegration< - TCreateOptions extends unknown[], - TResolvers extends - | { - [name in string]: (...args: any[]) => SignInResolver; - }, ->(config: { - create: (...args: TCreateOptions) => AuthProviderFactory; - resolvers?: TResolvers; -}): Readonly<{ - create: (...args: TCreateOptions) => AuthProviderFactory; - // If no resolvers are defined, this receives the type `never` - resolvers: Readonly; -}> { - return Object.freeze({ - ...config, - resolvers: Object.freeze(config.resolvers ?? ({} as any)), - }); -} diff --git a/plugins/auth-backend/src/providers/gcp-iap/index.ts b/plugins/auth-backend/src/providers/gcp-iap/index.ts deleted file mode 100644 index 12f76ec142..0000000000 --- a/plugins/auth-backend/src/providers/gcp-iap/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { gcpIap } from './provider'; -export type { GcpIapResult, GcpIapTokenInfo } from './types'; diff --git a/plugins/auth-backend/src/providers/gcp-iap/provider.ts b/plugins/auth-backend/src/providers/gcp-iap/provider.ts deleted file mode 100644 index f40cb4ed25..0000000000 --- a/plugins/auth-backend/src/providers/gcp-iap/provider.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { gcpIapAuthenticator } from '@backstage/plugin-auth-backend-module-gcp-iap-provider'; -import { - SignInResolver, - createProxyAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { AuthHandler } from '../types'; -import { GcpIapResult } from './types'; - -/** - * Auth provider integration for Google Identity-Aware Proxy auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const gcpIap = createAuthProviderIntegration({ - create(options: { - /** - * The profile transformation function used to verify and convert the auth - * response into the profile that will be presented to the user. The default - * implementation just provides the authenticated email that the IAP - * presented. - */ - authHandler?: AuthHandler; - - /** - * Configures sign-in for this provider. - */ - signIn: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return createProxyAuthProviderFactory({ - authenticator: gcpIapAuthenticator, - profileTransform: options?.authHandler, - signInResolver: options?.signIn?.resolver, - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/gcp-iap/types.ts b/plugins/auth-backend/src/providers/gcp-iap/types.ts deleted file mode 100644 index b1f69318fc..0000000000 --- a/plugins/auth-backend/src/providers/gcp-iap/types.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - GcpIapTokenInfo as _GcpIapTokenInfo, - GcpIapResult as _GcpIapResult, -} from '@backstage/plugin-auth-backend-module-gcp-iap-provider'; - -/** - * The data extracted from an IAP token. - * - * @public - * @deprecated import from `@backstage/plugin-auth-backend-module-gcp-iap-provider` instead - */ -export type GcpIapTokenInfo = _GcpIapTokenInfo; - -/** - * The result of the initial auth challenge. This is the input to the auth - * callbacks. - * - * @public - * @deprecated import from `@backstage/plugin-auth-backend-module-gcp-iap-provider` instead - */ -export type GcpIapResult = _GcpIapResult; diff --git a/plugins/auth-backend/src/providers/github/index.ts b/plugins/auth-backend/src/providers/github/index.ts deleted file mode 100644 index 2f4bb1f6cd..0000000000 --- a/plugins/auth-backend/src/providers/github/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { github } from './provider'; -export type { GithubOAuthResult } from './provider'; diff --git a/plugins/auth-backend/src/providers/github/provider.ts b/plugins/auth-backend/src/providers/github/provider.ts deleted file mode 100644 index 6c6738ad57..0000000000 --- a/plugins/auth-backend/src/providers/github/provider.ts +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Profile as PassportProfile } from 'passport'; -import { AuthHandler, StateEncoder } from '../types'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - createOAuthProviderFactory, - OAuthAuthenticatorResult, - ProfileTransform, - SignInResolver, -} from '@backstage/plugin-auth-node'; -import { githubAuthenticator } from '@backstage/plugin-auth-backend-module-github-provider'; - -/** - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export type GithubOAuthResult = { - fullProfile: PassportProfile; - params: { - scope: string; - expires_in?: string; - refresh_token_expires_in?: string; - }; - accessToken: string; - refreshToken?: string; -}; - -/** - * Auth provider integration for GitHub auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const github = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - - /** - * The state encoder used to encode the 'state' parameter on the OAuth request. - * - * It should return a string that takes the state params (from the request), url encodes the params - * and finally base64 encodes them. - * - * Providing your own stateEncoder will allow you to add addition parameters to the state field. - * - * It is typed as follows: - * `export type StateEncoder = (input: OAuthState) => Promise<{encodedState: string}>;` - * - * Note: the stateEncoder must encode a 'nonce' value and an 'env' value. Without this, the OAuth flow will fail - * (These two values will be set by the req.state by default) - * - * For more information, please see the helper module in ../../oauth/helpers #readState - */ - stateEncoder?: StateEncoder; - }) { - const authHandler = options?.authHandler; - const signInResolver = options?.signIn?.resolver; - return createOAuthProviderFactory({ - authenticator: githubAuthenticator, - profileTransform: - authHandler && - ((async (result, ctx) => - authHandler!( - { - fullProfile: result.fullProfile, - accessToken: result.session.accessToken, - params: { - scope: result.session.scope, - expires_in: result.session.expiresInSeconds - ? String(result.session.expiresInSeconds) - : '', - refresh_token_expires_in: result.session - .refreshTokenExpiresInSeconds - ? String(result.session.refreshTokenExpiresInSeconds) - : '', - }, - }, - ctx, - )) as ProfileTransform>), - signInResolver: - signInResolver && - ((async ({ profile, result }, ctx) => - signInResolver( - { - profile: profile, - result: { - fullProfile: result.fullProfile, - accessToken: result.session.accessToken, - refreshToken: result.session.refreshToken, - params: { - scope: result.session.scope, - expires_in: result.session.expiresInSeconds - ? String(result.session.expiresInSeconds) - : '', - refresh_token_expires_in: result.session - .refreshTokenExpiresInSeconds - ? String(result.session.refreshTokenExpiresInSeconds) - : '', - }, - }, - }, - ctx, - )) as SignInResolver>), - }); - }, - resolvers: { - /** - * Looks up the user by matching their GitHub username to the entity name. - */ - usernameMatchingUserEntityName: (): SignInResolver => { - return async (info, ctx) => { - const { fullProfile } = info.result; - - const userId = fullProfile.username; - if (!userId) { - throw new Error(`GitHub user profile does not contain a username`); - } - - return ctx.signInWithCatalogUser({ entityRef: { name: userId } }); - }; - }, - }, -}); diff --git a/plugins/auth-backend/src/providers/gitlab/index.ts b/plugins/auth-backend/src/providers/gitlab/index.ts deleted file mode 100644 index 9b60d1f18a..0000000000 --- a/plugins/auth-backend/src/providers/gitlab/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { gitlab } from './provider'; diff --git a/plugins/auth-backend/src/providers/gitlab/provider.ts b/plugins/auth-backend/src/providers/gitlab/provider.ts deleted file mode 100644 index 503145a805..0000000000 --- a/plugins/auth-backend/src/providers/gitlab/provider.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AuthHandler } from '../types'; -import { OAuthResult } from '../../lib/oauth'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - SignInResolver, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, -} from '../../lib/legacy'; -import { gitlabAuthenticator } from '@backstage/plugin-auth-backend-module-gitlab-provider'; - -/** - * Auth provider integration for GitLab auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const gitlab = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: gitlabAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/google/index.ts b/plugins/auth-backend/src/providers/google/index.ts deleted file mode 100644 index 5e8c3236e4..0000000000 --- a/plugins/auth-backend/src/providers/google/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { google } from './provider'; diff --git a/plugins/auth-backend/src/providers/google/provider.test.ts b/plugins/auth-backend/src/providers/google/provider.test.ts deleted file mode 100644 index abde2b66d1..0000000000 --- a/plugins/auth-backend/src/providers/google/provider.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { googleAuthenticator } from '@backstage/plugin-auth-backend-module-google-provider'; -import { createOAuthProviderFactory } from '@backstage/plugin-auth-node'; -import { google } from './provider'; - -jest.mock('@backstage/plugin-auth-node', () => ({ - ...jest.requireActual('@backstage/plugin-auth-node'), - createOAuthProviderFactory: jest.fn(() => 'provider-factory'), -})); - -describe('createGoogleProvider', () => { - afterEach(() => jest.clearAllMocks()); - - it('should be created', async () => { - expect(google.create()).toBe('provider-factory'); - - expect(createOAuthProviderFactory).toHaveBeenCalledWith({ - authenticator: googleAuthenticator, - }); - }); - - it('should be created with sign-in resolver', async () => { - expect(google.create({ signIn: { resolver: jest.fn() } })).toBe( - 'provider-factory', - ); - - expect(createOAuthProviderFactory).toHaveBeenCalledWith({ - authenticator: googleAuthenticator, - signInResolver: expect.any(Function), - }); - }); - - it('should be created with sign-in resolver and auth handler', async () => { - expect( - google.create({ - signIn: { resolver: jest.fn() }, - authHandler: jest.fn(), - }), - ).toBe('provider-factory'); - - expect(createOAuthProviderFactory).toHaveBeenCalledWith({ - authenticator: googleAuthenticator, - signInResolver: expect.any(Function), - profileTransform: expect.any(Function), - }); - }); - - it('should have resolvers', () => { - expect(google.resolvers).toEqual({ - emailLocalPartMatchingUserEntityName: expect.any(Function), - emailMatchingUserEntityAnnotation: expect.any(Function), - emailMatchingUserEntityProfileEmail: expect.any(Function), - }); - }); -}); diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts deleted file mode 100644 index 99a9c40ecb..0000000000 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - googleAuthenticator, - googleSignInResolvers, -} from '@backstage/plugin-auth-backend-module-google-provider'; -import { - SignInResolver, - commonSignInResolvers, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, - adaptOAuthSignInResolverToLegacy, -} from '../../lib/legacy'; -import { OAuthResult } from '../../lib/oauth'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { AuthHandler } from '../types'; - -/** - * Auth provider integration for Google auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const google = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: googleAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, - resolvers: adaptOAuthSignInResolverToLegacy({ - emailLocalPartMatchingUserEntityName: - commonSignInResolvers.emailLocalPartMatchingUserEntityName(), - emailMatchingUserEntityProfileEmail: - commonSignInResolvers.emailMatchingUserEntityProfileEmail(), - emailMatchingUserEntityAnnotation: - googleSignInResolvers.emailMatchingUserEntityAnnotation(), - }), -}); diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index b9543c275c..560ee25cc3 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -14,30 +14,8 @@ * limitations under the License. */ -export type { AwsAlbResult } from './aws-alb'; -export type { EasyAuthResult } from './azure-easyauth'; -export type { - BitbucketOAuthResult, - BitbucketPassportProfile, -} from './bitbucket'; -export type { BitbucketServerOAuthResult } from './bitbucketServer'; -export type { - CloudflareAccessClaims, - CloudflareAccessGroup, - CloudflareAccessResult, - CloudflareAccessIdentityProfile, -} from './cloudflare-access'; -export type { GithubOAuthResult } from './github'; -export type { OAuth2ProxyResult } from './oauth2-proxy'; -export type { OidcAuthResult } from './oidc'; -export type { SamlAuthResult } from './saml'; -export type { GcpIapResult, GcpIapTokenInfo } from './gcp-iap'; - -export { providers, defaultAuthProviderFactories } from './providers'; export { createOriginFilter, type ProviderFactories } from './router'; -export { createAuthProviderIntegration } from './createAuthProviderIntegration'; - export type { AuthProviderConfig, AuthProviderRouteHandlers, @@ -54,5 +32,3 @@ export type { ProfileInfo, OAuthStartResponse, } from './types'; - -export { prepareBackstageIdentityResponse } from './prepareBackstageIdentityResponse'; diff --git a/plugins/auth-backend/src/providers/microsoft/index.ts b/plugins/auth-backend/src/providers/microsoft/index.ts deleted file mode 100644 index 16dadc3bb0..0000000000 --- a/plugins/auth-backend/src/providers/microsoft/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { microsoft } from './provider'; diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts deleted file mode 100644 index f461fe8341..0000000000 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AuthHandler } from '../types'; -import { OAuthResult } from '../../lib/oauth'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - SignInResolver, - commonSignInResolvers, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, - adaptOAuthSignInResolverToLegacy, -} from '../../lib/legacy'; -import { - microsoftAuthenticator, - microsoftSignInResolvers, -} from '@backstage/plugin-auth-backend-module-microsoft-provider'; - -/** - * Auth provider integration for Microsoft auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const microsoft = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: microsoftAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, - resolvers: adaptOAuthSignInResolverToLegacy({ - emailLocalPartMatchingUserEntityName: - commonSignInResolvers.emailLocalPartMatchingUserEntityName(), - emailMatchingUserEntityProfileEmail: - commonSignInResolvers.emailMatchingUserEntityProfileEmail(), - emailMatchingUserEntityAnnotation: - microsoftSignInResolvers.emailMatchingUserEntityAnnotation(), - userIdMatchingUserEntityAnnotation: - microsoftSignInResolvers.userIdMatchingUserEntityAnnotation(), - }), -}); diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/index.ts b/plugins/auth-backend/src/providers/oauth2-proxy/index.ts deleted file mode 100644 index 2e4e7d016f..0000000000 --- a/plugins/auth-backend/src/providers/oauth2-proxy/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { oauth2Proxy } from './provider'; -import { OAuth2ProxyResult as _OAuth2ProxyResult } from '@backstage/plugin-auth-backend-module-oauth2-proxy-provider'; - -/** - * @public - * @deprecated import from `@backstage/plugin-auth-backend-module-oauth2-proxy-provider` instead - */ -export type OAuth2ProxyResult = _OAuth2ProxyResult; diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts deleted file mode 100644 index cbd02d18ea..0000000000 --- a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - SignInResolver, - createProxyAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { AuthHandler } from '../types'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - type OAuth2ProxyResult, - oauth2ProxyAuthenticator, -} from '@backstage/plugin-auth-backend-module-oauth2-proxy-provider'; - -/** - * Auth provider integration for oauth2-proxy auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const oauth2Proxy = createAuthProviderIntegration({ - create(options: { - /** - * Configure an auth handler to generate a profile for the user. - * - * The default implementation uses the value of the `X-Forwarded-Preferred-Username` - * header as the display name, falling back to `X-Forwarded-User`, and the value of - * the `X-Forwarded-Email` header as the email address. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return createProxyAuthProviderFactory({ - authenticator: oauth2ProxyAuthenticator, - profileTransform: options?.authHandler, - signInResolver: options?.signIn?.resolver, - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/oauth2/index.ts b/plugins/auth-backend/src/providers/oauth2/index.ts deleted file mode 100644 index 14485e04ff..0000000000 --- a/plugins/auth-backend/src/providers/oauth2/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { oauth2 } from './provider'; diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts deleted file mode 100644 index b9ab928730..0000000000 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { OAuthResult } from '../../lib/oauth'; -import { AuthHandler } from '../types'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, -} from '../../lib/legacy'; -import { - SignInResolver, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { oauth2Authenticator } from '@backstage/plugin-auth-backend-module-oauth2-provider'; - -/** - * Auth provider integration for generic OAuth2 auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const oauth2 = createAuthProviderIntegration({ - create(options?: { - authHandler?: AuthHandler; - - signIn?: { - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: oauth2Authenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/oidc/index.ts b/plugins/auth-backend/src/providers/oidc/index.ts deleted file mode 100644 index 501f223fb3..0000000000 --- a/plugins/auth-backend/src/providers/oidc/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { oidc } from './provider'; - -import { OidcAuthResult as OidcAuthResult_ } from '@backstage/plugin-auth-backend-module-oidc-provider'; - -/** - * @public - * @deprecated Use OidcAuthResult from `@backstage/plugin-auth-backend-module-oidc-provider` instead - */ -export type OidcAuthResult = OidcAuthResult_; diff --git a/plugins/auth-backend/src/providers/oidc/provider.test.ts b/plugins/auth-backend/src/providers/oidc/provider.test.ts deleted file mode 100644 index 773c5c8bb9..0000000000 --- a/plugins/auth-backend/src/providers/oidc/provider.test.ts +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { - mockServices, - registerMswTestHooks, -} from '@backstage/backend-test-utils'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { Config, ConfigReader } from '@backstage/config'; -import { - AuthProviderConfig, - AuthResolverContext, - CookieConfigurer, -} from '@backstage/plugin-auth-node'; -import express from 'express'; -import { JWK, SignJWT, exportJWK, generateKeyPair } from 'jose'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { oidc } from './provider'; - -describe('oidc.create', () => { - const userinfo = { - sub: 'test', - iss: 'https://oidc.test', - aud: 'clientId', - nonce: 'foo', - }; - const server = setupServer(); - registerMswTestHooks(server); - - let publicKey: JWK; - let tokenset: object; - let providerFactoryOptions: { - providerId: string; - globalConfig: AuthProviderConfig; - config: Config; - logger: LoggerService; - resolverContext: AuthResolverContext; - baseUrl: string; - appUrl: string; - isOriginAllowed: (origin: string) => boolean; - cookieConfigurer?: CookieConfigurer; - }; - - beforeAll(async () => { - const keyPair = await generateKeyPair('RS256'); - const privateKey = await exportJWK(keyPair.privateKey); - publicKey = await exportJWK(keyPair.publicKey); - publicKey.alg = privateKey.alg = 'RS256'; - - tokenset = { - id_token: await new SignJWT({ - iat: Date.now(), - exp: Date.now() + 10000, - ...userinfo, - }) - .setProtectedHeader({ alg: privateKey.alg, kid: privateKey.kid }) - .sign(keyPair.privateKey), - access_token: 'accessToken', - }; - }); - - beforeEach(() => { - server.use( - rest.get( - 'https://oidc.test/.well-known/openid-configuration', - (_req, res, ctx) => - res( - ctx.json({ - issuer: 'https://oidc.test', - token_endpoint: 'https://oidc.test/oauth2/token', - userinfo_endpoint: 'https://oidc.test/idp/userinfo.openid', - jwks_uri: 'https://oidc.test/jwks.json', - }), - ), - ), - rest.post('https://oidc.test/oauth2/token', (_req, res, ctx) => - res(ctx.json(tokenset)), - ), - rest.get('https://oidc.test/jwks.json', async (_req, res, ctx) => - res(ctx.json({ keys: [{ ...publicKey }] })), - ), - rest.get( - 'https://oidc.test/idp/userinfo.openid', - async (_req, res, ctx) => res(ctx.json(userinfo)), - ), - ); - providerFactoryOptions = { - providerId: 'myoidc', - baseUrl: 'http://backstage.test/api/auth', - appUrl: 'http://backstage.test', - isOriginAllowed: _ => true, - globalConfig: { - baseUrl: 'http://backstage.test/api/auth', - appUrl: 'http://backstage.test', - isOriginAllowed: _ => true, - }, - config: new ConfigReader({ - development: { - metadataUrl: 'https://oidc.test/.well-known/openid-configuration', - clientId: 'clientId', - clientSecret: 'clientSecret', - }, - }), - logger: mockServices.logger.mock(), - resolverContext: { - issueToken: jest.fn(), - findCatalogUser: jest.fn(), - signInWithCatalogUser: jest.fn(), - resolveOwnershipEntityRefs: jest.fn(), - }, - }; - }); - - it('invokes authHandler with tokenset and userinfo response', async () => { - const authHandler = jest.fn(); - const provider = oidc.create({ authHandler })(providerFactoryOptions); - const state = Buffer.from('nonce=foo&env=development').toString('hex'); - - await provider.frameHandler( - { - method: 'GET', - url: `http://backstage.test/api/auth/myoidc/handler/frame?code=blahblah&state=${state}`, - query: { state }, - cookies: { 'myoidc-nonce': 'foo' }, - session: { 'oidc:oidc.test': { state, nonce: 'foo' } }, - } as unknown as express.Request, - { setHeader: jest.fn(), end: jest.fn() } as unknown as express.Response, - ); - - expect(authHandler).toHaveBeenCalledWith( - { tokenset, userinfo }, - providerFactoryOptions.resolverContext, - ); - }); - - it('invokes sign-in resolver with tokenset and userinfo response', async () => { - const resolver = jest.fn(); - const provider = oidc.create({ signIn: { resolver } })( - providerFactoryOptions, - ); - const state = Buffer.from('nonce=foo&env=development').toString('hex'); - - await provider.frameHandler( - { - method: 'GET', - url: `http://backstage.test/api/auth/myoidc/handler/frame?code=blahblah&state=${state}`, - query: { state }, - cookies: { 'myoidc-nonce': 'foo' }, - session: { 'oidc:oidc.test': { state, nonce: 'foo' } }, - } as unknown as express.Request, - { setHeader: jest.fn(), end: jest.fn() } as unknown as express.Response, - ); - - expect(resolver).toHaveBeenCalledWith( - expect.objectContaining({ result: { tokenset, userinfo } }), - providerFactoryOptions.resolverContext, - ); - }); -}); diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts deleted file mode 100644 index 6caf97ef7c..0000000000 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AuthHandler } from '../types'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - createOAuthProviderFactory, - AuthResolverContext, - BackstageSignInResult, - OAuthAuthenticatorResult, - SignInInfo, - SignInResolver, -} from '@backstage/plugin-auth-node'; -import { - oidcAuthenticator, - OidcAuthResult, -} from '@backstage/plugin-auth-backend-module-oidc-provider'; -import { - commonByEmailLocalPartResolver, - commonByEmailResolver, -} from '../resolvers'; - -/** - * Auth provider integration for generic OpenID Connect auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const oidc = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider; convert user profile respones into - * Backstage identities. - */ - signIn?: { - resolver: SignInResolver; - }; - }) { - const authHandler = options?.authHandler; - const signInResolver = options?.signIn?.resolver; - return createOAuthProviderFactory({ - authenticator: oidcAuthenticator, - profileTransform: - authHandler && - (( - result: OAuthAuthenticatorResult, - context: AuthResolverContext, - ) => authHandler(result.fullProfile, context)), - signInResolver: - signInResolver && - (( - info: SignInInfo>, - context: AuthResolverContext, - ): Promise => - signInResolver( - { - result: info.result.fullProfile, - profile: info.profile, - }, - context, - )), - }); - }, - resolvers: { - /** - * Looks up the user by matching their email local part to the entity name. - */ - emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver, - /** - * Looks up the user by matching their email to the entity email. - */ - emailMatchingUserEntityProfileEmail: () => commonByEmailResolver, - }, -}); diff --git a/plugins/auth-backend/src/providers/okta/index.ts b/plugins/auth-backend/src/providers/okta/index.ts deleted file mode 100644 index 3387fa3668..0000000000 --- a/plugins/auth-backend/src/providers/okta/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { okta } from './provider'; diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts deleted file mode 100644 index 5746e12710..0000000000 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AuthHandler } from '../types'; -import { OAuthResult } from '../../lib/oauth'; - -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { - SignInResolver, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, -} from '../../lib/legacy'; -import { oktaAuthenticator } from '@backstage/plugin-auth-backend-module-okta-provider'; -import { - commonByEmailLocalPartResolver, - commonByEmailResolver, -} from '../resolvers'; - -/** - * Auth provider integration for Okta auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const okta = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: oktaAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, - resolvers: { - /** - * Looks up the user by matching their email local part to the entity name. - */ - emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver, - /** - * Looks up the user by matching their email to the entity email. - */ - emailMatchingUserEntityProfileEmail: () => commonByEmailResolver, - /** - * Looks up the user by matching their email to the `okta.com/email` annotation. - */ - emailMatchingUserEntityAnnotation(): SignInResolver { - return async (info, ctx) => { - const { profile } = info; - - if (!profile.email) { - throw new Error('Okta profile contained no email'); - } - - return ctx.signInWithCatalogUser({ - annotations: { - 'okta.com/email': profile.email, - }, - }); - }; - }, - }, -}); diff --git a/plugins/auth-backend/src/providers/onelogin/index.ts b/plugins/auth-backend/src/providers/onelogin/index.ts deleted file mode 100644 index 3f356029fb..0000000000 --- a/plugins/auth-backend/src/providers/onelogin/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { onelogin } from './provider'; diff --git a/plugins/auth-backend/src/providers/onelogin/provider.ts b/plugins/auth-backend/src/providers/onelogin/provider.ts deleted file mode 100644 index 808e6c15d3..0000000000 --- a/plugins/auth-backend/src/providers/onelogin/provider.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { oneLoginAuthenticator } from '@backstage/plugin-auth-backend-module-onelogin-provider'; -import { - SignInResolver, - createOAuthProviderFactory, -} from '@backstage/plugin-auth-node'; -import { - adaptLegacyOAuthHandler, - adaptLegacyOAuthSignInResolver, -} from '../../lib/legacy'; -import { OAuthResult } from '../../lib/oauth'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { AuthHandler } from '../types'; - -/** - * Auth provider integration for OneLogin auth - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const onelogin = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return createOAuthProviderFactory({ - authenticator: oneLoginAuthenticator, - profileTransform: adaptLegacyOAuthHandler(options?.authHandler), - signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), - }); - }, -}); diff --git a/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts b/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts deleted file mode 100644 index 1fa8f4a2fa..0000000000 --- a/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { prepareBackstageIdentityResponse as _prepareBackstageIdentityResponse } from '@backstage/plugin-auth-node'; - -/** - * @public - * @deprecated import from `@backstage/plugin-auth-node` instead - */ -export const prepareBackstageIdentityResponse = - _prepareBackstageIdentityResponse; diff --git a/plugins/auth-backend/src/providers/providers.ts b/plugins/auth-backend/src/providers/providers.ts deleted file mode 100644 index ce513e6ac7..0000000000 --- a/plugins/auth-backend/src/providers/providers.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { atlassian } from './atlassian'; -import { auth0 } from './auth0'; -import { awsAlb } from './aws-alb'; -import { bitbucket } from './bitbucket'; -import { cfAccess } from './cloudflare-access'; -import { gcpIap } from './gcp-iap'; -import { github } from './github'; -import { gitlab } from './gitlab'; -import { google } from './google'; -import { microsoft } from './microsoft'; -import { oauth2 } from './oauth2'; -import { oauth2Proxy } from './oauth2-proxy'; -import { oidc } from './oidc'; -import { okta } from './okta'; -import { onelogin } from './onelogin'; -import { saml } from './saml'; -import { bitbucketServer } from './bitbucketServer'; -import { easyAuth } from './azure-easyauth'; -import { AuthProviderFactory } from '@backstage/plugin-auth-node'; - -/** - * All built-in auth provider integrations. - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const providers = Object.freeze({ - atlassian, - auth0, - awsAlb, - bitbucket, - bitbucketServer, - cfAccess, - gcpIap, - github, - gitlab, - google, - microsoft, - oauth2, - oauth2Proxy, - oidc, - okta, - onelogin, - saml, - easyAuth, -}); - -/** - * All auth provider factories that are installed by default. - * - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export const defaultAuthProviderFactories: { - [providerId: string]: AuthProviderFactory; -} = { - google: google.create(), - github: github.create(), - gitlab: gitlab.create(), - saml: saml.create(), - okta: okta.create(), - auth0: auth0.create(), - microsoft: microsoft.create(), - easyAuth: easyAuth.create(), - oauth2: oauth2.create(), - oidc: oidc.create(), - onelogin: onelogin.create(), - awsalb: awsAlb.create(), - bitbucket: bitbucket.create(), - bitbucketServer: bitbucketServer.create(), - atlassian: atlassian.create(), -}; diff --git a/plugins/auth-backend/src/providers/saml/index.ts b/plugins/auth-backend/src/providers/saml/index.ts deleted file mode 100644 index d59f7bf0a7..0000000000 --- a/plugins/auth-backend/src/providers/saml/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { saml } from './provider'; -export type { SamlAuthResult } from './provider'; diff --git a/plugins/auth-backend/src/providers/saml/provider.ts b/plugins/auth-backend/src/providers/saml/provider.ts deleted file mode 100644 index 7797de897b..0000000000 --- a/plugins/auth-backend/src/providers/saml/provider.ts +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import express from 'express'; -import { SamlConfig, VerifiedCallback } from '@node-saml/passport-saml'; -import { - Strategy as SamlStrategy, - Profile as SamlProfile, - VerifyWithoutRequest, -} from '@node-saml/passport-saml'; -import { - executeFrameHandlerStrategy, - executeRedirectStrategy, -} from '../../lib/passport'; -import { AuthHandler } from '../types'; -import { postMessageResponse } from '../../lib/flow'; -import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { AuthenticationError, isError } from '@backstage/errors'; -import { prepareBackstageIdentityResponse } from '../prepareBackstageIdentityResponse'; -import { - AuthProviderRouteHandlers, - AuthResolverContext, - ClientAuthResponse, - SignInResolver, -} from '@backstage/plugin-auth-node'; - -/** - * @public - * @deprecated Migrate the auth plugin to the new backend system https://backstage.io/docs/backend-system/building-backends/migrating#the-auth-plugin - */ -export type SamlAuthResult = { - fullProfile: any; -}; - -type Options = SamlConfig & { - signInResolver?: SignInResolver; - authHandler: AuthHandler; - resolverContext: AuthResolverContext; - appUrl: string; -}; - -export class SamlAuthProvider implements AuthProviderRouteHandlers { - private readonly strategy: SamlStrategy; - private readonly signInResolver?: SignInResolver; - private readonly authHandler: AuthHandler; - private readonly resolverContext: AuthResolverContext; - private readonly appUrl: string; - - constructor(options: Options) { - this.appUrl = options.appUrl; - this.signInResolver = options.signInResolver; - this.authHandler = options.authHandler; - this.resolverContext = options.resolverContext; - - const verifier: VerifyWithoutRequest = ( - profile: SamlProfile | null, - done: VerifiedCallback, - ) => { - // TODO: There's plenty more validation and profile handling to do here, - // this provider is currently only intended to validate the provider pattern - // for non-oauth auth flows. - // TODO: This flow doesn't issue an identity token that can be used to validate - // the identity of the user in other backends, which we need in some form. - done(null, { fullProfile: profile }); - }; - this.strategy = new SamlStrategy(options, verifier, verifier); - } - - async start(req: express.Request, res: express.Response): Promise { - const { url } = await executeRedirectStrategy(req, this.strategy, {}); - res.redirect(url); - } - - async frameHandler( - req: express.Request, - res: express.Response, - ): Promise { - try { - const { result } = await executeFrameHandlerStrategy( - req, - this.strategy, - ); - - const { profile } = await this.authHandler(result, this.resolverContext); - - const response: ClientAuthResponse<{}> = { - profile, - providerInfo: {}, - }; - - if (this.signInResolver) { - const signInResponse = await this.signInResolver( - { - result, - profile, - }, - this.resolverContext, - ); - - response.backstageIdentity = - prepareBackstageIdentityResponse(signInResponse); - } - - return postMessageResponse(res, this.appUrl, { - type: 'authorization_response', - response, - }); - } catch (error) { - const { name, message } = isError(error) - ? error - : new Error('Encountered invalid error'); // Being a bit safe and not forwarding the bad value - return postMessageResponse(res, this.appUrl, { - type: 'authorization_response', - error: { name, message }, - }); - } - } - - async logout(_req: express.Request, res: express.Response): Promise { - res.end(); - } -} - -type SignatureAlgorithm = 'sha1' | 'sha256' | 'sha512'; - -/** - * Auth provider integration for SAML auth - * - * @public - */ -export const saml = createAuthProviderIntegration({ - create(options?: { - /** - * The profile transformation function used to verify and convert the auth response - * into the profile that will be presented to the user. - */ - authHandler?: AuthHandler; - - /** - * Configure sign-in for this provider, without it the provider can not be used to sign users in. - */ - signIn?: { - /** - * Maps an auth result to a Backstage identity for the user. - */ - resolver: SignInResolver; - }; - }) { - return ({ providerId, globalConfig, config, resolverContext }) => { - const authHandler: AuthHandler = options?.authHandler - ? options.authHandler - : async ({ fullProfile }) => ({ - profile: { - email: fullProfile.email, - displayName: fullProfile.displayName, - }, - }); - - return new SamlAuthProvider({ - callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`, - entryPoint: config.getString('entryPoint'), - logoutUrl: config.getOptionalString('logoutUrl'), - audience: config.getString('audience'), - issuer: config.getString('issuer'), - idpCert: config.getString('cert'), - privateKey: config.getOptionalString('privateKey'), - authnContext: config.getOptionalStringArray('authnContext'), - identifierFormat: config.getOptionalString('identifierFormat'), - decryptionPvk: config.getOptionalString('decryptionPvk'), - signatureAlgorithm: config.getOptionalString('signatureAlgorithm') as - | SignatureAlgorithm - | undefined, - digestAlgorithm: config.getOptionalString('digestAlgorithm'), - acceptedClockSkewMs: config.getOptionalNumber('acceptedClockSkewMs'), - wantAuthnResponseSigned: config.getOptionalBoolean( - 'wantAuthnResponseSigned', - ), - wantAssertionsSigned: config.getOptionalBoolean('wantAssertionsSigned'), - appUrl: globalConfig.appUrl, - authHandler, - signInResolver: options?.signIn?.resolver, - resolverContext, - }); - }; - }, - resolvers: { - /** - * Looks up the user by matching their nameID to the entity name. - */ - nameIdMatchingUserEntityName(): SignInResolver { - return async (info, ctx) => { - const id = info.result.fullProfile.nameID; - - if (!id) { - throw new AuthenticationError('No nameID found in SAML response'); - } - - return ctx.signInWithCatalogUser({ - entityRef: { name: id }, - }); - }; - }, - }, -}); diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index af34ffc310..070c9f905f 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -25,7 +25,6 @@ import { LoggerService, RootConfigService, } from '@backstage/backend-plugin-api'; -import { defaultAuthProviderFactories } from '../providers'; import { AuthOwnershipResolver } from '@backstage/plugin-auth-node'; import { TokenManager, @@ -49,10 +48,6 @@ import { StaticTokenIssuer } from '../identity/StaticTokenIssuer'; import { StaticKeyStore } from '../identity/StaticKeyStore'; import { bindProviderRouters, ProviderFactories } from '../providers/router'; -/** - * @public - * @deprecated Please migrate to the new backend system as this will be removed in the future. - */ export interface RouterOptions { logger: LoggerService; database: DatabaseService; @@ -63,15 +58,10 @@ export interface RouterOptions { httpAuth?: HttpAuthService; tokenFactoryAlgorithm?: string; providerFactories?: ProviderFactories; - disableDefaultProviderFactories?: boolean; catalogApi?: CatalogApi; ownershipResolver?: AuthOwnershipResolver; } -/** - * @public - * @deprecated Please migrate to the new backend system as this will be removed in the future. - */ export async function createRouter( options: RouterOptions, ): Promise { @@ -151,15 +141,8 @@ export async function createRouter( router.use(express.urlencoded({ extended: false })); router.use(express.json()); - const providers = options.disableDefaultProviderFactories - ? providerFactories - : { - ...defaultAuthProviderFactories, - ...providerFactories, - }; - bindProviderRouters(router, { - providers, + providers: providerFactories, appUrl, baseUrl: authUrl, tokenIssuer, diff --git a/yarn.lock b/yarn.lock index c6ba66b2f0..3337a6ee2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4902,7 +4902,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-atlassian-provider@workspace:^, @backstage/plugin-auth-backend-module-atlassian-provider@workspace:plugins/auth-backend-module-atlassian-provider": +"@backstage/plugin-auth-backend-module-atlassian-provider@workspace:plugins/auth-backend-module-atlassian-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-atlassian-provider@workspace:plugins/auth-backend-module-atlassian-provider" dependencies: @@ -4920,7 +4920,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-auth0-provider@workspace:^, @backstage/plugin-auth-backend-module-auth0-provider@workspace:plugins/auth-backend-module-auth0-provider": +"@backstage/plugin-auth-backend-module-auth0-provider@workspace:plugins/auth-backend-module-auth0-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-auth0-provider@workspace:plugins/auth-backend-module-auth0-provider" dependencies: @@ -4940,7 +4940,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-aws-alb-provider@workspace:^, @backstage/plugin-auth-backend-module-aws-alb-provider@workspace:plugins/auth-backend-module-aws-alb-provider": +"@backstage/plugin-auth-backend-module-aws-alb-provider@workspace:plugins/auth-backend-module-aws-alb-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-aws-alb-provider@workspace:plugins/auth-backend-module-aws-alb-provider" dependencies: @@ -4959,7 +4959,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-azure-easyauth-provider@workspace:^, @backstage/plugin-auth-backend-module-azure-easyauth-provider@workspace:plugins/auth-backend-module-azure-easyauth-provider": +"@backstage/plugin-auth-backend-module-azure-easyauth-provider@workspace:plugins/auth-backend-module-azure-easyauth-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-azure-easyauth-provider@workspace:plugins/auth-backend-module-azure-easyauth-provider" dependencies: @@ -4977,7 +4977,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-bitbucket-provider@workspace:^, @backstage/plugin-auth-backend-module-bitbucket-provider@workspace:plugins/auth-backend-module-bitbucket-provider": +"@backstage/plugin-auth-backend-module-bitbucket-provider@workspace:plugins/auth-backend-module-bitbucket-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-bitbucket-provider@workspace:plugins/auth-backend-module-bitbucket-provider" dependencies: @@ -4995,7 +4995,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-bitbucket-server-provider@workspace:^, @backstage/plugin-auth-backend-module-bitbucket-server-provider@workspace:plugins/auth-backend-module-bitbucket-server-provider": +"@backstage/plugin-auth-backend-module-bitbucket-server-provider@workspace:plugins/auth-backend-module-bitbucket-server-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-bitbucket-server-provider@workspace:plugins/auth-backend-module-bitbucket-server-provider" dependencies: @@ -5013,7 +5013,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-cloudflare-access-provider@workspace:^, @backstage/plugin-auth-backend-module-cloudflare-access-provider@workspace:plugins/auth-backend-module-cloudflare-access-provider": +"@backstage/plugin-auth-backend-module-cloudflare-access-provider@workspace:plugins/auth-backend-module-cloudflare-access-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-cloudflare-access-provider@workspace:plugins/auth-backend-module-cloudflare-access-provider" dependencies: @@ -5034,7 +5034,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-gcp-iap-provider@workspace:^, @backstage/plugin-auth-backend-module-gcp-iap-provider@workspace:plugins/auth-backend-module-gcp-iap-provider": +"@backstage/plugin-auth-backend-module-gcp-iap-provider@workspace:plugins/auth-backend-module-gcp-iap-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-gcp-iap-provider@workspace:plugins/auth-backend-module-gcp-iap-provider" dependencies: @@ -5065,7 +5065,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-gitlab-provider@workspace:^, @backstage/plugin-auth-backend-module-gitlab-provider@workspace:plugins/auth-backend-module-gitlab-provider": +"@backstage/plugin-auth-backend-module-gitlab-provider@workspace:plugins/auth-backend-module-gitlab-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-gitlab-provider@workspace:plugins/auth-backend-module-gitlab-provider" dependencies: @@ -5083,7 +5083,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-google-provider@workspace:^, @backstage/plugin-auth-backend-module-google-provider@workspace:plugins/auth-backend-module-google-provider": +"@backstage/plugin-auth-backend-module-google-provider@workspace:plugins/auth-backend-module-google-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-google-provider@workspace:plugins/auth-backend-module-google-provider" dependencies: @@ -5116,7 +5116,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-microsoft-provider@workspace:^, @backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider": +"@backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider" dependencies: @@ -5137,7 +5137,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-oauth2-provider@workspace:^, @backstage/plugin-auth-backend-module-oauth2-provider@workspace:plugins/auth-backend-module-oauth2-provider": +"@backstage/plugin-auth-backend-module-oauth2-provider@workspace:plugins/auth-backend-module-oauth2-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-oauth2-provider@workspace:plugins/auth-backend-module-oauth2-provider" dependencies: @@ -5154,7 +5154,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-oauth2-proxy-provider@workspace:^, @backstage/plugin-auth-backend-module-oauth2-proxy-provider@workspace:plugins/auth-backend-module-oauth2-proxy-provider": +"@backstage/plugin-auth-backend-module-oauth2-proxy-provider@workspace:plugins/auth-backend-module-oauth2-proxy-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-oauth2-proxy-provider@workspace:plugins/auth-backend-module-oauth2-proxy-provider" dependencies: @@ -5167,7 +5167,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-oidc-provider@workspace:^, @backstage/plugin-auth-backend-module-oidc-provider@workspace:plugins/auth-backend-module-oidc-provider": +"@backstage/plugin-auth-backend-module-oidc-provider@workspace:plugins/auth-backend-module-oidc-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-oidc-provider@workspace:plugins/auth-backend-module-oidc-provider" dependencies: @@ -5191,7 +5191,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-okta-provider@workspace:^, @backstage/plugin-auth-backend-module-okta-provider@workspace:plugins/auth-backend-module-okta-provider": +"@backstage/plugin-auth-backend-module-okta-provider@workspace:plugins/auth-backend-module-okta-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-okta-provider@workspace:plugins/auth-backend-module-okta-provider" dependencies: @@ -5209,7 +5209,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend-module-onelogin-provider@workspace:^, @backstage/plugin-auth-backend-module-onelogin-provider@workspace:plugins/auth-backend-module-onelogin-provider": +"@backstage/plugin-auth-backend-module-onelogin-provider@workspace:plugins/auth-backend-module-onelogin-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-onelogin-provider@workspace:plugins/auth-backend-module-onelogin-provider" dependencies: @@ -5286,23 +5286,6 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" - "@backstage/plugin-auth-backend-module-atlassian-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-auth0-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-aws-alb-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-bitbucket-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-gcp-iap-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-github-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-gitlab-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-google-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-microsoft-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-oauth2-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-oidc-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-okta-provider": "workspace:^" - "@backstage/plugin-auth-backend-module-onelogin-provider": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/types": "workspace:^"