diff --git a/.changeset/angry-candles-kick.md b/.changeset/angry-candles-kick.md
new file mode 100644
index 0000000000..6f51f719c2
--- /dev/null
+++ b/.changeset/angry-candles-kick.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-auth-backend': patch
+---
+
+Add new authentication provider: OAuth2Proxy
diff --git a/docs/auth/index.md b/docs/auth/index.md
index 4a8d225048..e407480f65 100644
--- a/docs/auth/index.md
+++ b/docs/auth/index.md
@@ -25,6 +25,7 @@ Backstage comes with many common authentication providers in the core library:
- [Google](google/provider.md)
- [Okta](okta/provider.md)
- [OneLogin](onelogin/provider.md)
+- [OAuth2Proxy](oauth2-proxy/provider.md)
These built-in providers handle the authentication flow for a particular service
including required scopes, callbacks, etc. These providers are each added to a
diff --git a/docs/auth/oauth2-proxy/provider.md b/docs/auth/oauth2-proxy/provider.md
new file mode 100644
index 0000000000..326b5ef463
--- /dev/null
+++ b/docs/auth/oauth2-proxy/provider.md
@@ -0,0 +1,105 @@
+---
+id: provider
+title: OAuth 2 Proxy Provider
+sidebar_label: OAuth 2 Custom Proxy
+description: Adding OAuth2Proxy as an authentication provider in Backstage
+---
+
+The Backstage `@backstage/plugin-auth-backend` package comes with an
+`oauth2proxy` authentication provider that can authenticate users by using a
+[oauth2-proxy](https://github.com/oauth2-proxy/oauth2-proxy) in front of an
+actual Backstage instance. This enables to reuse existing authentications within
+a cluster. In general the `oauth2-proxy` supports all OpenID Connect providers,
+for more details check this
+[list of supported providers](https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/oauth_provider).
+
+## Configuration
+
+The provider configuration can be added to your `app-config.yaml` under the root
+`auth` configuration:
+
+```yaml
+auth:
+ environment: development
+ providers:
+ oauth2proxy: {}
+```
+
+Right now no configuration options are supported. To make use of the provider,
+make sure that your `oauth2-proxy` is configured correctly and provides a custom
+`X-OAUTH2-PROXY-ID-TOKEN` header. To do so, enable the
+`--set-authorization-header=true` of your `oauth2-proxy` and forward the
+`Authorization` header as `X-OAUTH2-PROXY-ID-TOKEN`. For more details check the
+[configuration docs](https://oauth2-proxy.github.io/oauth2-proxy/configuration).
+
+_Example for kubernetes ingress:_
+
+```bash
+# forward the authorization header from the auth request in the X-OAUTH2-PROXY-ID-TOKEN header
+auth_request_set $name_upstream_authorization $upstream_http_authorization;
+proxy_set_header X-OAUTH2-PROXY-ID-TOKEN $name_upstream_authorization;
+```
+
+## Adding the provider to the Backstage backend
+
+When using `oauth2proxy` auth you can configure it as described
+[here](https://backstage.io/docs/auth/identity-resolver).
+
+- use the following code below to introduce changes to
+ `packages/backend/plugin/auth.ts`:
+
+```ts
+ providerFactories: {
+ oauth2proxy: createOauth2ProxyProvider<{
+ id: string;
+ email: string;
+ }>({
+ authHandler: async input => {
+ const { email } = input.fullProfile;
+
+ return {
+ profile: {
+ email,
+ },
+ };
+ },
+ signIn: {
+ resolver: async (signInInfo, ctx) => {
+ const { preferred_username: id } = signInInfo.result.fullProfile;
+ const sub = `user:default/${id}`;
+
+ const token = await ctx.tokenIssuer.issueToken({
+ claims: { sub, ent: [`group:default/optional-user-group`] },
+ });
+
+ return { id, token };
+ },
+ },
+ }),
+ }
+```
+
+## Adding the provider to the Backstage frontend
+
+All Backstage apps need a `SignInPage` to be configured. Its purpose is to
+establish who the user is and what their identifying credentials are, blocking
+rendering the rest of the UI until that's complete, and then keeping those
+credentials fresh.
+
+When using the OAuth2-Proxy, the Backstage UI can only be accessed after the
+user has already been authenticated at the proxy. Instead of showing the user
+another login page when accessing Backstage, it will handle the login in the
+background. Backstage provides for this case a special `SignInPage` component
+which has no UI.
+
+Update your `createApp` call in `packages/app/src/App.tsx`, as follows.
+
+```diff
++import { ProxiedSignInPage } from '@backstage/core-components';
+ const app = createApp({
+ components: {
++ SignInPage: props => ,
+```
+
+After this, your app should be ready to leverage the OAuth2-Proxy for
+authentication!
diff --git a/microsite/sidebars.json b/microsite/sidebars.json
index c0a0b9b24f..48d44e9a21 100644
--- a/microsite/sidebars.json
+++ b/microsite/sidebars.json
@@ -228,7 +228,8 @@
"auth/gitlab/provider",
"auth/google/provider",
"auth/okta/provider",
- "auth/onelogin/provider"
+ "auth/onelogin/provider",
+ "auth/oauth2-proxy/provider"
]
},
"auth/add-auth-provider",
diff --git a/mkdocs.yml b/mkdocs.yml
index 398863a3c0..2fcdb830d9 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -144,6 +144,7 @@ nav:
- Google: 'auth/google/provider.md'
- Okta: 'auth/okta/provider.md'
- OneLogin: 'auth/onelogin/provider.md'
+ - OAuth2Proxy: 'auth/oauth2-proxy/provider.md'
- Bitbucket: 'auth/bitbucket/provider.md'
- Adding authentication providers: 'auth/add-auth-provider.md'
- Using authentication and identity: 'auth/using-auth.md'
diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md
index 01de316de0..db0bf2af27 100644
--- a/plugins/auth-backend/api-report.md
+++ b/plugins/auth-backend/api-report.md
@@ -59,9 +59,17 @@ export type Auth0ProviderOptions = {
};
};
+// @public
+export type AuthContext = {
+ tokenIssuer: TokenIssuer;
+ catalogIdentityClient: CatalogIdentityClient;
+ logger: Logger_2;
+};
+
// @public
export type AuthHandler = (
input: TAuthResult,
+ context?: AuthContext,
) => Promise;
// @public
@@ -270,6 +278,11 @@ export const createOAuth2Provider: (
options?: OAuth2ProviderOptions | undefined,
) => AuthProviderFactory;
+// @public
+export const createOauth2ProxyProvider: (
+ options: Oauth2ProxyProviderOptions,
+) => AuthProviderFactory;
+
// Warning: (ae-missing-release-tag) "createOidcProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -436,6 +449,20 @@ export type OAuth2ProviderOptions = {
};
};
+// @public
+export type Oauth2ProxyProviderOptions = {
+ authHandler: AuthHandler>;
+ signIn: {
+ resolver: SignInResolver>;
+ };
+};
+
+// @public
+export type OAuth2ProxyResult = {
+ fullProfile: JWTPayload;
+ accessToken: string;
+};
+
// Warning: (ae-missing-release-tag) "OAuthAdapter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -664,11 +691,7 @@ export type SignInInfo = {
// @public
export type SignInResolver = (
info: SignInInfo,
- context: {
- tokenIssuer: TokenIssuer;
- catalogIdentityClient: CatalogIdentityClient;
- logger: Logger_2;
- },
+ context: AuthContext,
) => Promise;
// Warning: (ae-missing-release-tag) "TokenIssuer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -704,5 +727,5 @@ export type WebMessageResponse =
// src/identity/types.d.ts:31:9 - (ae-forgotten-export) The symbol "AnyJWK" needs to be exported by the entry point index.d.ts
// src/providers/aws-alb/provider.d.ts:77:5 - (ae-forgotten-export) The symbol "AwsAlbResult" needs to be exported by the entry point index.d.ts
// src/providers/github/provider.d.ts:81:5 - (ae-forgotten-export) The symbol "StateEncoder" needs to be exported by the entry point index.d.ts
-// src/providers/types.d.ts:88:5 - (ae-forgotten-export) The symbol "AuthProviderConfig" needs to be exported by the entry point index.d.ts
+// src/providers/types.d.ts:98:5 - (ae-forgotten-export) The symbol "AuthProviderConfig" needs to be exported by the entry point index.d.ts
```
diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts
index a25d2ce8bc..79575c2a77 100644
--- a/plugins/auth-backend/src/providers/index.ts
+++ b/plugins/auth-backend/src/providers/index.ts
@@ -23,6 +23,7 @@ export * from './gitlab';
export * from './google';
export * from './microsoft';
export * from './oauth2';
+export * from './oauth2-proxy';
export * from './oidc';
export * from './okta';
export * from './onelogin';
@@ -38,6 +39,7 @@ export type {
AuthProviderFactoryOptions,
AuthProviderFactory,
AuthHandler,
+ AuthContext,
AuthHandlerResult,
SignInResolver,
SignInInfo,
diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/index.ts b/plugins/auth-backend/src/providers/oauth2-proxy/index.ts
new file mode 100644
index 0000000000..62304b1d1f
--- /dev/null
+++ b/plugins/auth-backend/src/providers/oauth2-proxy/index.ts
@@ -0,0 +1,18 @@
+/*
+ * 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 { createOauth2ProxyProvider } from './provider';
+export type { Oauth2ProxyProviderOptions, OAuth2ProxyResult } from './provider';
diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts
new file mode 100644
index 0000000000..4e1aeb88bf
--- /dev/null
+++ b/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+jest.mock('jose', () => ({
+ JWT: {
+ decode: jest.fn(),
+ },
+}));
+jest.mock('@backstage/catalog-client');
+
+import express from 'express';
+import { JWT } from 'jose';
+import { Logger } from 'winston';
+import {
+ AuthHandler,
+ SignInResolver,
+ AuthProviderFactoryOptions,
+} from '../types';
+
+import { CatalogIdentityClient } from '../../lib/catalog';
+import { TokenIssuer } from '../../identity/types';
+
+import {
+ createOauth2ProxyProvider,
+ Oauth2ProxyAuthProvider,
+ Oauth2ProxyProviderOptions,
+ OAuth2ProxyResult,
+ OAUTH2_PROXY_JWT_HEADER,
+} from './provider';
+
+describe('Oauth2ProxyAuthProvider', () => {
+ const mockToken =
+ 'eyblob.eyJzdWIiOiJqaW1teW1hcmt1bSIsImVudCI6WyJ1c2VyOmRlZmF1bHQvamltbXltYXJrdW0iXX0=.eyblob';
+
+ let provider: Oauth2ProxyAuthProvider;
+ let logger: jest.Mocked;
+ let signInResolver: jest.MockedFunction<
+ SignInResolver>
+ >;
+ let authHandler: jest.MockedFunction>>;
+ let mockResponse: jest.Mocked;
+ let mockRequest: jest.Mocked;
+ let JWTMock: jest.Mocked;
+
+ beforeEach(() => {
+ jest.resetAllMocks();
+
+ JWTMock = JWT as jest.Mocked;
+ authHandler = jest.fn();
+ signInResolver = jest.fn();
+ logger = { error: jest.fn() } as unknown as jest.Mocked;
+
+ mockResponse = {
+ status: jest.fn(),
+ end: jest.fn(),
+ json: jest.fn(),
+ } as unknown as jest.Mocked;
+
+ mockRequest = {
+ body: {},
+ header: jest.fn(),
+ } as unknown as jest.Mocked;
+
+ provider = new Oauth2ProxyAuthProvider({
+ authHandler,
+ logger,
+ signInResolver,
+ catalogIdentityClient: {} as CatalogIdentityClient,
+ tokenIssuer: {} as TokenIssuer,
+ });
+ });
+
+ describe('frameHandler()', () => {
+ it('should do nothing and return undefined', async () => {
+ const result = await provider.frameHandler();
+
+ expect(result).toBeUndefined();
+ });
+ });
+
+ describe('start()', () => {
+ it('should do nothing and return undefined', async () => {
+ const result = await provider.start();
+
+ expect(result).toBeUndefined();
+ });
+ });
+
+ describe('refresh()', () => {
+ 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);
+ });
+
+ 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);
+ });
+
+ it('should return if auth header is set and valid', async () => {
+ mockRequest.header.mockReturnValue(`Bearer token`);
+ authHandler.mockResolvedValue({
+ profile: {},
+ });
+ signInResolver.mockResolvedValue({
+ id: 'some-id',
+ token: mockToken,
+ });
+
+ await provider.refresh(mockRequest, mockResponse);
+
+ expect(mockRequest.header).toBeCalledWith(OAUTH2_PROXY_JWT_HEADER);
+ expect(JWTMock.decode).toHaveBeenCalledWith('token');
+ expect(mockResponse.json).toHaveBeenCalled();
+ });
+
+ it('should load profile from authHandler and backstage identity from signInResolver', async () => {
+ const decodedToken = {
+ oid: 'oid',
+ name: 'name',
+ upn: 'john.doe@example.com',
+ };
+ const profile = { displayName: 'some value' };
+ mockRequest.header.mockReturnValue(`Bearer token`);
+ signInResolver.mockResolvedValue({
+ id: 'some-id',
+ token: mockToken,
+ });
+ authHandler.mockResolvedValue({ profile: profile });
+ JWTMock.decode.mockReturnValue(decodedToken as any);
+
+ await provider.refresh(mockRequest, mockResponse);
+
+ expect(signInResolver).toHaveBeenCalledWith(
+ {
+ profile: profile,
+ result: {
+ accessToken: 'token',
+ fullProfile: decodedToken,
+ },
+ },
+ { catalogIdentityClient: {}, logger, tokenIssuer: {} },
+ );
+ expect(mockResponse.json).toHaveBeenCalledWith({
+ backstageIdentity: {
+ id: 'some-id',
+ idToken: mockToken,
+ identity: {
+ ownershipEntityRefs: ['user:default/jimmymarkum'],
+ type: 'user',
+ userEntityRef: 'jimmymarkum',
+ },
+ token: mockToken,
+ },
+ profile: { displayName: 'some value' },
+ providerInfo: {
+ accessToken: 'token',
+ },
+ });
+ });
+ });
+
+ describe('createOauth2ProxyProvider()', () => {
+ beforeEach(() => {
+ mockRequest.header.mockReturnValue(`Bearer token`);
+ authHandler.mockResolvedValue({
+ profile: {},
+ });
+ signInResolver.mockResolvedValue({
+ id: 'some-id',
+ token: mockToken,
+ });
+ });
+
+ it('should create a valid provider', async () => {
+ const providerOptions = {
+ authHandler,
+ signIn: { resolver: signInResolver },
+ } as Oauth2ProxyProviderOptions;
+ const factoryOptions = {
+ logger,
+ catalogApi: {},
+ tokenIssuer: {},
+ } as unknown as AuthProviderFactoryOptions;
+
+ const factory = createOauth2ProxyProvider(providerOptions);
+ const handler = factory(factoryOptions);
+ await handler.refresh!(mockRequest, mockResponse);
+
+ expect(mockRequest.header).toBeCalledWith(OAUTH2_PROXY_JWT_HEADER);
+ expect(JWTMock.decode).toHaveBeenCalledWith('token');
+ expect(mockResponse.json).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts
new file mode 100644
index 0000000000..eceebc5924
--- /dev/null
+++ b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts
@@ -0,0 +1,199 @@
+/*
+ * 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 express from 'express';
+import { Logger } from 'winston';
+import { AuthenticationError } from '@backstage/errors';
+import {
+ AuthHandler,
+ SignInResolver,
+ AuthProviderFactory,
+ AuthProviderRouteHandlers,
+ AuthResponse,
+} from '../types';
+import { CatalogIdentityClient } from '../../lib/catalog';
+import { JWT } from 'jose';
+import { IdentityClient } from '../../identity';
+import { TokenIssuer } from '../../identity/types';
+import { prepareBackstageIdentityResponse } from '../prepareBackstageIdentityResponse';
+
+export const OAUTH2_PROXY_JWT_HEADER = 'X-OAUTH2-PROXY-ID-TOKEN';
+
+/**
+ * JWT header extraction result, containing the raw value and the parsed JWT
+ * payload.
+ *
+ * @public
+ */
+export type OAuth2ProxyResult = {
+ /**
+ * Parsed and decoded JWT payload.
+ */
+ fullProfile: JWTPayload;
+
+ /**
+ * Raw JWT token
+ */
+ accessToken: string;
+};
+
+/**
+ * Options for the oauth2-proxy provider factory
+ *
+ * @public
+ */
+export type Oauth2ProxyProviderOptions = {
+ /**
+ * Configure an auth handler to generate a profile for 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>;
+ };
+};
+
+interface Options {
+ logger: Logger;
+ signInResolver: SignInResolver>;
+ authHandler: AuthHandler>;
+ tokenIssuer: TokenIssuer;
+ catalogIdentityClient: CatalogIdentityClient;
+}
+
+export class Oauth2ProxyAuthProvider
+ implements AuthProviderRouteHandlers
+{
+ private readonly logger: Logger;
+ private readonly catalogIdentityClient: CatalogIdentityClient;
+ 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.signInResolver = options.signInResolver;
+ this.authHandler = options.authHandler;
+ }
+
+ frameHandler(): Promise {
+ return Promise.resolve(undefined);
+ }
+
+ 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();
+ }
+ }
+
+ start(): Promise {
+ return Promise.resolve(undefined);
+ }
+
+ 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 backstageSignInResult = await this.signInResolver(
+ {
+ result,
+ profile,
+ },
+ ctx,
+ );
+
+ return {
+ providerInfo: {
+ accessToken: result.accessToken,
+ },
+ backstageIdentity: prepareBackstageIdentityResponse(
+ backstageSignInResult,
+ ),
+ profile,
+ };
+ }
+
+ private getResult(req: express.Request): OAuth2ProxyResult {
+ const authHeader = req.header(OAUTH2_PROXY_JWT_HEADER);
+ const jwt = IdentityClient.getBearerToken(authHeader);
+
+ if (!jwt) {
+ throw new AuthenticationError(
+ `Missing or in incorrect format - Oauth2Proxy OIDC header: ${OAUTH2_PROXY_JWT_HEADER}`,
+ );
+ }
+
+ const decodedJWT = JWT.decode(jwt) as unknown as JWTPayload;
+
+ return {
+ fullProfile: decodedJWT,
+ accessToken: jwt,
+ };
+ }
+}
+
+/**
+ * Factory function for oauth2-proxy auth provider
+ *
+ * @public
+ */
+export const createOauth2ProxyProvider =
+ (
+ options: Oauth2ProxyProviderOptions,
+ ): AuthProviderFactory =>
+ ({ catalogApi, logger, tokenIssuer }) => {
+ const signInResolver = options.signIn.resolver;
+ const authHandler = options.authHandler;
+ const catalogIdentityClient = new CatalogIdentityClient({
+ catalogApi,
+ tokenIssuer,
+ });
+ return new Oauth2ProxyAuthProvider({
+ logger,
+ signInResolver,
+ authHandler,
+ tokenIssuer,
+ catalogIdentityClient,
+ });
+ };
diff --git a/plugins/auth-backend/src/providers/oauth2/index.ts b/plugins/auth-backend/src/providers/oauth2/index.ts
index d68208a148..767466f8f6 100644
--- a/plugins/auth-backend/src/providers/oauth2/index.ts
+++ b/plugins/auth-backend/src/providers/oauth2/index.ts
@@ -15,4 +15,5 @@
*/
export { createOAuth2Provider } from './provider';
+
export type { OAuth2ProviderOptions } from './provider';
diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts
index dabe46a9ae..b1aad05897 100644
--- a/plugins/auth-backend/src/providers/types.ts
+++ b/plugins/auth-backend/src/providers/types.ts
@@ -24,6 +24,17 @@ import { TokenIssuer } from '../identity/types';
import { OAuthStartRequest } from '../lib/oauth/types';
import { CatalogIdentityClient } from '../lib/catalog';
+/**
+ * The context that is used for auth processing.
+ *
+ * @public
+ */
+export type AuthContext = {
+ tokenIssuer: TokenIssuer;
+ catalogIdentityClient: CatalogIdentityClient;
+ logger: Logger;
+};
+
export type AuthProviderConfig = {
/**
* The protocol://domain[:port] where the app is hosted. This is used to construct the
@@ -259,11 +270,7 @@ export type SignInInfo = {
*/
export type SignInResolver = (
info: SignInInfo,
- context: {
- tokenIssuer: TokenIssuer;
- catalogIdentityClient: CatalogIdentityClient;
- logger: Logger;
- },
+ context: AuthContext,
) => Promise;
/**
@@ -289,6 +296,7 @@ export type AuthHandlerResult = { profile: ProfileInfo };
*/
export type AuthHandler = (
input: TAuthResult,
+ context?: AuthContext,
) => Promise;
export type StateEncoder = (