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 efede36212..e27713acb3 100644 --- a/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts +++ b/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts @@ -21,18 +21,14 @@ jest.mock('jose', () => ({ })); jest.mock('@backstage/catalog-client'); +import { AuthenticationError } from '@backstage/errors'; import express from 'express'; import { JWT } from 'jose'; import { Logger } from 'winston'; -import { AuthHandler, SignInResolver } from '../types'; - -import { CatalogIdentityClient } from '../../lib/catalog'; -import { TokenIssuer } from '../../identity/types'; - +import { AuthHandler, AuthResolverContext, SignInResolver } from '../types'; import { createOauth2ProxyProvider, Oauth2ProxyAuthProvider, - Oauth2ProxyProviderOptions, OAuth2ProxyResult, OAUTH2_PROXY_JWT_HEADER, } from './provider'; @@ -72,10 +68,10 @@ describe('Oauth2ProxyAuthProvider', () => { provider = new Oauth2ProxyAuthProvider({ authHandler, - logger, signInResolver, - catalogIdentityClient: {} as CatalogIdentityClient, - tokenIssuer: {} as TokenIssuer, + resolverContext: { + _: 'resolver-context', + } as unknown as AuthResolverContext, }); }); @@ -99,17 +95,17 @@ describe('Oauth2ProxyAuthProvider', () => { it('should throw an error when auth header is missing', async () => { mockRequest.header.mockReturnValue(undefined); - await provider.refresh(mockRequest, mockResponse); - - expect(mockResponse.status).toHaveBeenCalledWith(401); + await expect(provider.refresh(mockRequest, mockResponse)).rejects.toThrow( + AuthenticationError, + ); }); it('should throw an error if the bearer token is invalid', async () => { mockRequest.header.mockReturnValue('Basic asdf='); - await provider.refresh(mockRequest, mockResponse); - - expect(mockResponse.status).toHaveBeenCalledWith(401); + await expect(provider.refresh(mockRequest, mockResponse)).rejects.toThrow( + AuthenticationError, + ); }); it('should return if auth header is set and valid', async () => { @@ -152,7 +148,7 @@ describe('Oauth2ProxyAuthProvider', () => { fullProfile: decodedToken, }, }, - { catalogIdentityClient: {}, logger, tokenIssuer: {} }, + { _: 'resolver-context' }, ); expect(mockResponse.json).toHaveBeenCalledWith({ backstageIdentity: { @@ -183,12 +179,10 @@ describe('Oauth2ProxyAuthProvider', () => { }); it('should create a valid provider', async () => { - const providerOptions = { + const factory = createOauth2ProxyProvider({ authHandler, signIn: { resolver: signInResolver }, - } as Oauth2ProxyProviderOptions; - - const factory = createOauth2ProxyProvider(providerOptions); + }); const handler = factory({ logger, catalogApi: {}, diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts index f89f759270..ed3e5bce81 100644 --- a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts @@ -15,7 +15,6 @@ */ import express from 'express'; -import { Logger } from 'winston'; import { AuthenticationError } from '@backstage/errors'; import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { @@ -24,10 +23,9 @@ import { AuthProviderFactory, AuthProviderRouteHandlers, AuthResponse, + AuthResolverContext, } from '../types'; -import { CatalogIdentityClient } from '../../lib/catalog'; import { JWT } from 'jose'; -import { TokenIssuer } from '../../identity/types'; import { prepareBackstageIdentityResponse } from '../prepareBackstageIdentityResponse'; export const OAUTH2_PROXY_JWT_HEADER = 'X-OAUTH2-PROXY-ID-TOKEN'; @@ -71,28 +69,22 @@ export type Oauth2ProxyProviderOptions = { }; interface Options { - logger: Logger; + resolverContext: AuthResolverContext; signInResolver: SignInResolver>; authHandler: AuthHandler>; - tokenIssuer: TokenIssuer; - catalogIdentityClient: CatalogIdentityClient; } export class Oauth2ProxyAuthProvider implements AuthProviderRouteHandlers { - private readonly logger: Logger; - private readonly catalogIdentityClient: CatalogIdentityClient; + private readonly resolverContext: AuthResolverContext; private readonly signInResolver: SignInResolver< OAuth2ProxyResult >; private readonly authHandler: AuthHandler>; - private readonly tokenIssuer: TokenIssuer; constructor(options: Options) { - this.catalogIdentityClient = options.catalogIdentityClient; - this.logger = options.logger; - this.tokenIssuer = options.tokenIssuer; + this.resolverContext = options.resolverContext; this.signInResolver = options.signInResolver; this.authHandler = options.authHandler; } @@ -104,17 +96,10 @@ export class Oauth2ProxyAuthProvider async refresh(req: express.Request, res: express.Response): Promise { try { const result = this.getResult(req); - const response = await this.handleResult(result); - res.json(response); } catch (e) { - this.logger.error( - `Exception occurred during ${OAUTH2_PROXY_JWT_HEADER} refresh`, - e, - ); - res.status(401); - res.end(); + throw new AuthenticationError('Refresh failed', e); } } @@ -125,20 +110,14 @@ export class Oauth2ProxyAuthProvider private async handleResult( result: OAuth2ProxyResult, ): Promise> { - const ctx = { - logger: this.logger, - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - }; - - const { profile } = await this.authHandler(result, ctx); + const { profile } = await this.authHandler(result, this.resolverContext); const backstageSignInResult = await this.signInResolver( { result, profile, }, - ctx, + this.resolverContext, ); return { @@ -193,18 +172,12 @@ export const createOauth2ProxyProvider = resolver: SignInResolver>; }; }): AuthProviderFactory => - ({ catalogApi, logger, tokenIssuer, tokenManager }) => { + ({ resolverContext }) => { const signInResolver = options.signIn.resolver; const authHandler = options.authHandler; - const catalogIdentityClient = new CatalogIdentityClient({ - catalogApi, - tokenManager, - }); return new Oauth2ProxyAuthProvider({ - logger, + resolverContext, signInResolver, authHandler, - tokenIssuer, - catalogIdentityClient, }); };