diff --git a/plugins/auth-backend/src/providers/google/provider.test.ts b/plugins/auth-backend/src/providers/google/provider.test.ts index a69a7b0485..c31833d561 100644 --- a/plugins/auth-backend/src/providers/google/provider.test.ts +++ b/plugins/auth-backend/src/providers/google/provider.test.ts @@ -39,10 +39,12 @@ describe('createGoogleProvider', () => { }; const provider = new GoogleAuthProvider({ - logger: getVoidLogger(), - catalogIdentityClient: - catalogIdentityClient as unknown as CatalogIdentityClient, - tokenIssuer: tokenIssuer as unknown as TokenIssuer, + resolverContext: { + logger: getVoidLogger(), + catalogIdentityClient: + catalogIdentityClient as unknown as CatalogIdentityClient, + tokenIssuer: tokenIssuer as unknown as TokenIssuer, + }, authHandler: async ({ fullProfile }) => ({ profile: { email: fullProfile.emails![0]!.value, diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 68c505cc43..10187c4d97 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -17,8 +17,7 @@ import express from 'express'; import passport from 'passport'; import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; -import { TokenIssuer } from '../../identity/types'; -import { CatalogIdentityClient, getEntityClaims } from '../../lib/catalog'; +import { getEntityClaims } from '../../lib/catalog'; import { encodeState, OAuthAdapter, @@ -38,8 +37,12 @@ import { makeProfileInfo, PassportDoneCallback, } from '../../lib/passport'; -import { AuthHandler, RedirectInfo, SignInResolver } from '../types'; -import { Logger } from 'winston'; +import { + AuthHandler, + AuthResolverContext, + RedirectInfo, + SignInResolver, +} from '../types'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; import { commonByEmailLocalPartResolver } from '../resolvers'; @@ -50,26 +53,20 @@ type PrivateInfo = { type Options = OAuthProviderOptions & { signInResolver?: SignInResolver; authHandler: AuthHandler; - tokenIssuer: TokenIssuer; - catalogIdentityClient: CatalogIdentityClient; - logger: Logger; + resolverContext: AuthResolverContext; }; export class GoogleAuthProvider implements OAuthHandlers { - private readonly _strategy: GoogleStrategy; + private readonly strategy: GoogleStrategy; private readonly signInResolver?: SignInResolver; private readonly authHandler: AuthHandler; - private readonly tokenIssuer: TokenIssuer; - private readonly catalogIdentityClient: CatalogIdentityClient; - private readonly logger: Logger; + private readonly resolverContext: AuthResolverContext; constructor(options: Options) { - this.signInResolver = options.signInResolver; this.authHandler = options.authHandler; - this.tokenIssuer = options.tokenIssuer; - this.catalogIdentityClient = options.catalogIdentityClient; - this.logger = options.logger; - this._strategy = new GoogleStrategy( + this.signInResolver = options.signInResolver; + this.resolverContext = options.resolverContext; + this.strategy = new GoogleStrategy( { clientID: options.clientId, clientSecret: options.clientSecret, @@ -102,7 +99,7 @@ export class GoogleAuthProvider implements OAuthHandlers { } async start(req: OAuthStartRequest): Promise { - return await executeRedirectStrategy(req, this._strategy, { + return await executeRedirectStrategy(req, this.strategy, { accessType: 'offline', prompt: 'consent', scope: req.scope, @@ -114,7 +111,7 @@ export class GoogleAuthProvider implements OAuthHandlers { const { result, privateInfo } = await executeFrameHandlerStrategy< OAuthResult, PrivateInfo - >(req, this._strategy); + >(req, this.strategy); return { response: await this.handleResult(result), @@ -125,12 +122,12 @@ export class GoogleAuthProvider implements OAuthHandlers { async refresh(req: OAuthRefreshRequest) { const { accessToken, refreshToken, params } = await executeRefreshTokenStrategy( - this._strategy, + this.strategy, req.refreshToken, req.scope, ); const fullProfile = await executeFetchUserProfileStrategy( - this._strategy, + this.strategy, accessToken, ); @@ -145,12 +142,7 @@ export class GoogleAuthProvider implements OAuthHandlers { } private async handleResult(result: OAuthResult) { - const context = { - logger: this.logger, - catalogIdentityClient: this.catalogIdentityClient, - tokenIssuer: this.tokenIssuer, - }; - const { profile } = await this.authHandler(result, context); + const { profile } = await this.authHandler(result, this.resolverContext); const response: OAuthResponse = { providerInfo: { @@ -168,7 +160,7 @@ export class GoogleAuthProvider implements OAuthHandlers { result, profile, }, - context, + this.resolverContext, ); } @@ -215,15 +207,7 @@ export const google = createAuthProviderIntegration({ resolver: SignInResolver; }; }) { - return ({ - providerId, - globalConfig, - config, - tokenIssuer, - tokenManager, - catalogApi, - logger, - }) => + return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, envConfig => { const clientId = envConfig.getString('clientId'); const clientSecret = envConfig.getString('clientSecret'); @@ -232,11 +216,6 @@ export const google = createAuthProviderIntegration({ customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`; - const catalogIdentityClient = new CatalogIdentityClient({ - catalogApi, - tokenManager, - }); - const authHandler: AuthHandler = options?.authHandler ? options.authHandler : async ({ fullProfile, params }) => ({ @@ -249,15 +228,12 @@ export const google = createAuthProviderIntegration({ callbackUrl, signInResolver: options?.signIn?.resolver, authHandler, - tokenIssuer, - catalogIdentityClient, - logger, + resolverContext, }); return OAuthAdapter.fromConfig(globalConfig, provider, { disableRefresh: false, providerId, - tokenIssuer, callbackUrl, }); }); diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts index 61f08bc535..efede36212 100644 --- a/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts +++ b/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts @@ -24,11 +24,7 @@ jest.mock('@backstage/catalog-client'); import express from 'express'; import { JWT } from 'jose'; import { Logger } from 'winston'; -import { - AuthHandler, - SignInResolver, - AuthProviderFactoryOptions, -} from '../types'; +import { AuthHandler, SignInResolver } from '../types'; import { CatalogIdentityClient } from '../../lib/catalog'; import { TokenIssuer } from '../../identity/types'; @@ -191,14 +187,13 @@ describe('Oauth2ProxyAuthProvider', () => { authHandler, signIn: { resolver: signInResolver }, } as Oauth2ProxyProviderOptions; - const factoryOptions = { + + const factory = createOauth2ProxyProvider(providerOptions); + const handler = factory({ logger, catalogApi: {}, tokenIssuer: {}, - } as unknown as AuthProviderFactoryOptions; - - const factory = createOauth2ProxyProvider(providerOptions); - const handler = factory(factoryOptions); + } as any); await handler.refresh!(mockRequest, mockResponse); expect(mockRequest.header).toBeCalledWith(OAUTH2_PROXY_JWT_HEADER); diff --git a/plugins/auth-backend/src/providers/oidc/provider.test.ts b/plugins/auth-backend/src/providers/oidc/provider.test.ts index d9902b600e..13fe1ae46b 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.test.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.test.ts @@ -23,7 +23,6 @@ import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { ClientMetadata, IssuerMetadata } from 'openid-client'; import { OAuthAdapter } from '../../lib/oauth'; -import { AuthProviderFactoryOptions } from '../types'; import { createOidcProvider, OidcAuthProvider, Options } from './provider'; import { getVoidLogger } from '@backstage/backend-common'; @@ -178,14 +177,13 @@ describe('OidcAuthProvider', () => { metadataUrl: 'https://oidc.test/.well-known/openid-configuration', }, } as any); - const options = { + const provider = createOidcProvider()({ globalConfig: { appUrl: 'https://oidc.test', baseUrl: 'https://oidc.test', }, config, - } as AuthProviderFactoryOptions; - const provider = createOidcProvider()(options) as OAuthAdapter; + } as any) as OAuthAdapter; expect(provider.start).toBeDefined(); // Cast provider as any here to be able to inspect private members await (provider as any).handlers.get('testEnv').handlers.implementation; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 5bd52f0c94..ce77a650e3 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -143,6 +143,9 @@ export interface AuthProviderRouteHandlers { logout?(req: express.Request, res: express.Response): Promise; } +/** + * @deprecated This type is deprecated and will be removed in a future release. + */ export type AuthProviderFactoryOptions = { providerId: string; globalConfig: AuthProviderConfig; @@ -154,9 +157,23 @@ export type AuthProviderFactoryOptions = { catalogApi: CatalogApi; }; -export type AuthProviderFactory = ( - options: AuthProviderFactoryOptions, -) => AuthProviderRouteHandlers; +export type AuthProviderFactory = (options: { + providerId: string; + globalConfig: AuthProviderConfig; + config: Config; + resolverContext: AuthResolverContext; + + /** @deprecated This field has been deprecated and needs to be passed directly to the auth provider instead */ + logger: Logger; + /** @deprecated This field has been deprecated and needs to be passed directly to the auth provider instead */ + tokenManager: TokenManager; + /** @deprecated This field has been deprecated and needs to be passed directly to the auth provider instead */ + tokenIssuer: TokenIssuer; + /** @deprecated This field has been deprecated and needs to be passed directly to the auth provider instead */ + discovery: PluginEndpointDiscovery; + /** @deprecated This field has been deprecated and needs to be passed directly to the auth provider instead */ + catalogApi: CatalogApi; +}) => AuthProviderRouteHandlers; export type AuthResponse = { providerInfo: ProviderInfo; diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index ec1a52ffc9..42afe56bc0 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -34,6 +34,7 @@ import { createOidcRouter, TokenFactory, KeyStores } from '../identity'; import session from 'express-session'; import passport from 'passport'; import { Minimatch } from 'minimatch'; +import { CatalogIdentityClient } from '../lib/catalog'; type ProviderFactories = { [s: string]: AuthProviderFactory }; @@ -103,6 +104,11 @@ export async function createRouter( const isOriginAllowed = createOriginFilter(config); + const catalogIdentityClient = new CatalogIdentityClient({ + catalogApi, + tokenManager, + }); + for (const [providerId, providerFactory] of Object.entries( allProviderFactories, )) { @@ -122,6 +128,11 @@ export async function createRouter( tokenIssuer, discovery, catalogApi, + resolverContext: { + logger, + tokenIssuer, + catalogIdentityClient, + }, }); const r = Router();