diff --git a/.changeset/angry-candles-kick.md b/.changeset/angry-candles-kick.md index 6f51f719c2..d72882121e 100644 --- a/.changeset/angry-candles-kick.md +++ b/.changeset/angry-candles-kick.md @@ -1,5 +1,8 @@ --- -'@backstage/plugin-auth-backend': patch +'@backstage/plugin-auth-backend': minor --- -Add new authentication provider: OAuth2Proxy +Add new authentication provider to support the oauth2-proxy. + +**BREAKING** The `AuthHandler` requires now an `AuthResolverContext` parameter. This aligns with the +behavior of the `SignInResolver`. diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index db0bf2af27..07a09597ee 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -59,17 +59,10 @@ export type Auth0ProviderOptions = { }; }; -// @public -export type AuthContext = { - tokenIssuer: TokenIssuer; - catalogIdentityClient: CatalogIdentityClient; - logger: Logger_2; -}; - // @public export type AuthHandler = ( input: TAuthResult, - context?: AuthContext, + context: AuthResolverContext, ) => Promise; // @public @@ -107,6 +100,13 @@ export interface AuthProviderRouteHandlers { start(req: express.Request, res: express.Response): Promise; } +// @public +export type AuthResolverContext = { + tokenIssuer: TokenIssuer; + catalogIdentityClient: CatalogIdentityClient; + logger: Logger_2; +}; + // Warning: (ae-missing-release-tag) "AuthResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -691,7 +691,7 @@ export type SignInInfo = { // @public export type SignInResolver = ( info: SignInInfo, - context: AuthContext, + context: AuthResolverContext, ) => Promise; // Warning: (ae-missing-release-tag) "TokenIssuer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/auth-backend/src/providers/atlassian/provider.ts b/plugins/auth-backend/src/providers/atlassian/provider.ts index ba402eace0..9987a88407 100644 --- a/plugins/auth-backend/src/providers/atlassian/provider.ts +++ b/plugins/auth-backend/src/providers/atlassian/provider.ts @@ -120,7 +120,12 @@ export class AtlassianAuthProvider implements OAuthHandlers { } private async handleResult(result: OAuthResult): Promise { - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -138,11 +143,7 @@ export class AtlassianAuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/auth0/provider.ts b/plugins/auth-backend/src/providers/auth0/provider.ts index b99bbe86dd..dbd6924804 100644 --- a/plugins/auth-backend/src/providers/auth0/provider.ts +++ b/plugins/auth-backend/src/providers/auth0/provider.ts @@ -149,7 +149,12 @@ export class Auth0AuthProvider implements OAuthHandlers { } private async handleResult(result: OAuthResult) { - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -167,11 +172,7 @@ export class Auth0AuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/aws-alb/provider.ts b/plugins/auth-backend/src/providers/aws-alb/provider.ts index 4f05cd7827..cc111b4aaf 100644 --- a/plugins/auth-backend/src/providers/aws-alb/provider.ts +++ b/plugins/auth-backend/src/providers/aws-alb/provider.ts @@ -182,17 +182,18 @@ export class AwsAlbAuthProvider implements AuthProviderRouteHandlers { } private async handleResult(result: AwsAlbResult): Promise { - const { profile } = await this.authHandler(result); + const context = { + tokenIssuer: this.tokenIssuer, + catalogIdentityClient: this.catalogIdentityClient, + logger: this.logger, + }; + const { profile } = await this.authHandler(result, context); const backstageIdentity = await this.signInResolver( { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); return { diff --git a/plugins/auth-backend/src/providers/bitbucket/provider.ts b/plugins/auth-backend/src/providers/bitbucket/provider.ts index 5ad9a739d9..c83a195db5 100644 --- a/plugins/auth-backend/src/providers/bitbucket/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucket/provider.ts @@ -174,7 +174,12 @@ export class BitbucketAuthProvider implements OAuthHandlers { private async handleResult(result: BitbucketOAuthResult) { result.fullProfile.avatarUrl = result.fullProfile._json!.links!.avatar!.href; - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -192,11 +197,7 @@ export class BitbucketAuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/gcp-iap/provider.ts b/plugins/auth-backend/src/providers/gcp-iap/provider.ts index c74f73304e..a54c7e9fb2 100644 --- a/plugins/auth-backend/src/providers/gcp-iap/provider.ts +++ b/plugins/auth-backend/src/providers/gcp-iap/provider.ts @@ -71,16 +71,17 @@ export class GcpIapProvider implements AuthProviderRouteHandlers { req.header(IAP_JWT_HEADER), this.tokenValidator, ); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; - const { profile } = await this.authHandler(result); + const { profile } = await this.authHandler(result, context); const backstageIdentity = await this.signInResolver( { profile, result }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); const response: GcpIapResponse = { diff --git a/plugins/auth-backend/src/providers/github/provider.ts b/plugins/auth-backend/src/providers/github/provider.ts index 2984f144aa..c5ccdb2d59 100644 --- a/plugins/auth-backend/src/providers/github/provider.ts +++ b/plugins/auth-backend/src/providers/github/provider.ts @@ -152,7 +152,12 @@ export class GithubAuthProvider implements OAuthHandlers { } private async handleResult(result: GithubOAuthResult) { - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const expiresInStr = result.params.expires_in; const response: OAuthResponse = { @@ -171,11 +176,7 @@ export class GithubAuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/gitlab/provider.ts b/plugins/auth-backend/src/providers/gitlab/provider.ts index dedbb7bd5b..28deb458d9 100644 --- a/plugins/auth-backend/src/providers/gitlab/provider.ts +++ b/plugins/auth-backend/src/providers/gitlab/provider.ts @@ -167,7 +167,12 @@ export class GitlabAuthProvider implements OAuthHandlers { } private async handleResult(result: OAuthResult): Promise { - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -185,11 +190,7 @@ export class GitlabAuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 10123bfe6f..90e68c6f9c 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -148,7 +148,12 @@ export class GoogleAuthProvider implements OAuthHandlers { } private async handleResult(result: OAuthResult) { - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -166,11 +171,7 @@ export class GoogleAuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 79575c2a77..7779b67e04 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -39,7 +39,7 @@ export type { AuthProviderFactoryOptions, AuthProviderFactory, AuthHandler, - AuthContext, + AuthResolverContext, AuthHandlerResult, SignInResolver, SignInInfo, diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index 7e928a2786..c45e152581 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -143,7 +143,12 @@ export class MicrosoftAuthProvider implements OAuthHandlers { const photo = await this.getUserPhoto(result.accessToken); result.fullProfile.photos = photo ? [{ value: photo }] : undefined; - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -161,11 +166,7 @@ export class MicrosoftAuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts index dc4afbac48..550b88b004 100644 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2/provider.ts @@ -163,7 +163,12 @@ export class OAuth2AuthProvider implements OAuthHandlers { } private async handleResult(result: OAuthResult) { - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -181,11 +186,7 @@ export class OAuth2AuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts index e5bfd14f40..ab95495619 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.ts @@ -182,7 +182,12 @@ export class OidcAuthProvider implements OAuthHandlers { // Use this function to grab the user profile info from the token // Then populate the profile with it private async handleResult(result: OidcAuthResult): Promise { - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { idToken: result.tokenset.id_token, @@ -198,11 +203,7 @@ export class OidcAuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts index 1c74e171ad..a5c663ae68 100644 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ b/plugins/auth-backend/src/providers/okta/provider.ts @@ -169,7 +169,12 @@ export class OktaAuthProvider implements OAuthHandlers { } private async handleResult(result: OAuthResult) { - const { profile } = await this._authHandler(result); + const context = { + logger: this._logger, + catalogIdentityClient: this._catalogIdentityClient, + tokenIssuer: this._tokenIssuer, + }; + const { profile } = await this._authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -187,11 +192,7 @@ export class OktaAuthProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this._tokenIssuer, - catalogIdentityClient: this._catalogIdentityClient, - logger: this._logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/onelogin/provider.ts b/plugins/auth-backend/src/providers/onelogin/provider.ts index 4b2201e576..ea84b402d5 100644 --- a/plugins/auth-backend/src/providers/onelogin/provider.ts +++ b/plugins/auth-backend/src/providers/onelogin/provider.ts @@ -148,7 +148,12 @@ export class OneLoginProvider implements OAuthHandlers { } private async handleResult(result: OAuthResult) { - const { profile } = await this.authHandler(result); + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { profile } = await this.authHandler(result, context); const response: OAuthResponse = { providerInfo: { @@ -166,11 +171,7 @@ export class OneLoginProvider implements OAuthHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); } diff --git a/plugins/auth-backend/src/providers/saml/provider.ts b/plugins/auth-backend/src/providers/saml/provider.ts index 8a4afd1fa6..b9c8d89f5b 100644 --- a/plugins/auth-backend/src/providers/saml/provider.ts +++ b/plugins/auth-backend/src/providers/saml/provider.ts @@ -93,12 +93,18 @@ export class SamlAuthProvider implements AuthProviderRouteHandlers { res: express.Response, ): Promise { try { + const context = { + logger: this.logger, + catalogIdentityClient: this.catalogIdentityClient, + tokenIssuer: this.tokenIssuer, + }; + const { result } = await executeFrameHandlerStrategy( req, this.strategy, ); - const { profile } = await this.authHandler(result); + const { profile } = await this.authHandler(result, context); const response: AuthResponse<{}> = { profile, @@ -111,11 +117,7 @@ export class SamlAuthProvider implements AuthProviderRouteHandlers { result, profile, }, - { - tokenIssuer: this.tokenIssuer, - catalogIdentityClient: this.catalogIdentityClient, - logger: this.logger, - }, + context, ); response.backstageIdentity = diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index b1aad05897..179d536f3c 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -29,7 +29,7 @@ import { CatalogIdentityClient } from '../lib/catalog'; * * @public */ -export type AuthContext = { +export type AuthResolverContext = { tokenIssuer: TokenIssuer; catalogIdentityClient: CatalogIdentityClient; logger: Logger; @@ -270,7 +270,7 @@ export type SignInInfo = { */ export type SignInResolver = ( info: SignInInfo, - context: AuthContext, + context: AuthResolverContext, ) => Promise; /** @@ -296,7 +296,7 @@ export type AuthHandlerResult = { profile: ProfileInfo }; */ export type AuthHandler = ( input: TAuthResult, - context?: AuthContext, + context: AuthResolverContext, ) => Promise; export type StateEncoder = (