diff --git a/packages/backend/src/plugins/auth.ts b/packages/backend/src/plugins/auth.ts index 4e51518bc1..7f2b950c3c 100644 --- a/packages/backend/src/plugins/auth.ts +++ b/packages/backend/src/plugins/auth.ts @@ -23,6 +23,13 @@ export default async function createPlugin({ database, config, discovery, + tokenManager, }: PluginEnvironment): Promise { - return await createRouter({ logger, config, database, discovery }); + return await createRouter({ + logger, + config, + database, + discovery, + tokenManager, + }); } diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts index 52165104a2..f96c55910c 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts @@ -7,6 +7,7 @@ export default async function createPlugin({ database, config, discovery, + tokenManager, }: PluginEnvironment): Promise { - return await createRouter({ logger, config, database, discovery }); + return await createRouter({ logger, config, database, discovery, tokenManager }); } diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts index 0ddcaa6d2c..897233294f 100644 --- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts +++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts @@ -14,13 +14,13 @@ * limitations under the License. */ +import { TokenManager } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { RELATION_MEMBER_OF, UserEntity, UserEntityV1alpha1, } from '@backstage/catalog-model'; -import { TokenIssuer } from '../../identity'; import { CatalogIdentityClient } from './CatalogIdentityClient'; describe('CatalogIdentityClient', () => { @@ -36,19 +36,19 @@ describe('CatalogIdentityClient', () => { refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), }; - const tokenIssuer: jest.Mocked = { - issueToken: jest.fn(), - listPublicKeys: jest.fn(), + const tokenManager: jest.Mocked = { + getToken: jest.fn(), + authenticate: jest.fn(), }; afterEach(() => jest.resetAllMocks()); it('findUser passes through the correct search params', async () => { catalogApi.getEntities.mockResolvedValueOnce({ items: [{} as UserEntity] }); - tokenIssuer.issueToken.mockResolvedValue('my-token'); + tokenManager.getToken.mockResolvedValue({ token: 'my-token' }); const client = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); await client.findUser({ annotations: { key: 'value' } }); @@ -62,11 +62,7 @@ describe('CatalogIdentityClient', () => { }, { token: 'my-token' }, ); - expect(tokenIssuer.issueToken).toHaveBeenCalledWith({ - claims: { - sub: 'backstage.io/auth-backend', - }, - }); + expect(tokenManager.getToken).toHaveBeenCalledWith(); }); it('resolveCatalogMembership resolves membership', async () => { @@ -114,35 +110,39 @@ describe('CatalogIdentityClient', () => { }, ]; catalogApi.getEntities.mockResolvedValueOnce({ items: mockUsers }); + tokenManager.getToken.mockResolvedValue({ token: 'my-token' }); const client = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const claims = await client.resolveCatalogMembership({ entityRefs: ['inigom', 'User:default/imontoya', 'User:reality/mpatinkin'], }); - expect(catalogApi.getEntities).toHaveBeenCalledWith({ - filter: [ - { - kind: 'user', - 'metadata.namespace': 'default', - 'metadata.name': 'inigom', - }, - { - kind: 'user', - 'metadata.namespace': 'default', - 'metadata.name': 'imontoya', - }, - { - kind: 'user', - 'metadata.namespace': 'reality', - 'metadata.name': 'mpatinkin', - }, - ], - }); + expect(catalogApi.getEntities).toHaveBeenCalledWith( + { + filter: [ + { + kind: 'user', + 'metadata.namespace': 'default', + 'metadata.name': 'inigom', + }, + { + kind: 'user', + 'metadata.namespace': 'default', + 'metadata.name': 'imontoya', + }, + { + kind: 'user', + 'metadata.namespace': 'reality', + 'metadata.name': 'mpatinkin', + }, + ], + }, + { token: 'my-token' }, + ); expect(claims).toMatchObject([ 'user:default/inigom', diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts index a1f915d152..8341b186a9 100644 --- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts +++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts @@ -24,7 +24,7 @@ import { stringifyEntityRef, UserEntity, } from '@backstage/catalog-model'; -import { TokenIssuer } from '../../identity'; +import { TokenManager } from '@backstage/backend-common'; type UserQuery = { annotations: Record; @@ -40,11 +40,11 @@ type MemberClaimQuery = { */ export class CatalogIdentityClient { private readonly catalogApi: CatalogApi; - private readonly tokenIssuer: TokenIssuer; + private readonly tokenManager: TokenManager; - constructor(options: { catalogApi: CatalogApi; tokenIssuer: TokenIssuer }) { + constructor(options: { catalogApi: CatalogApi; tokenManager: TokenManager }) { this.catalogApi = options.catalogApi; - this.tokenIssuer = options.tokenIssuer; + this.tokenManager = options.tokenManager; } /** @@ -61,9 +61,7 @@ export class CatalogIdentityClient { } // TODO(Rugvip): cache the token - const token = await this.tokenIssuer.issueToken({ - claims: { sub: 'backstage.io/auth-backend' }, - }); + const { token } = await this.tokenManager.getToken(); const { items } = await this.catalogApi.getEntities({ filter }, { token }); if (items.length !== 1) { @@ -106,8 +104,9 @@ export class CatalogIdentityClient { 'metadata.namespace': ref.namespace, 'metadata.name': ref.name, })); + const { token } = await this.tokenManager.getToken(); const entities = await this.catalogApi - .getEntities({ filter }) + .getEntities({ filter }, { token }) .then(r => r.items); if (entityRefs.length !== entities.length) { diff --git a/plugins/auth-backend/src/providers/atlassian/provider.ts b/plugins/auth-backend/src/providers/atlassian/provider.ts index 9987a88407..2696fd233f 100644 --- a/plugins/auth-backend/src/providers/atlassian/provider.ts +++ b/plugins/auth-backend/src/providers/atlassian/provider.ts @@ -197,6 +197,7 @@ export const createAtlassianProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -208,7 +209,7 @@ export const createAtlassianProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = diff --git a/plugins/auth-backend/src/providers/auth0/provider.ts b/plugins/auth-backend/src/providers/auth0/provider.ts index dbd6924804..15578117ea 100644 --- a/plugins/auth-backend/src/providers/auth0/provider.ts +++ b/plugins/auth-backend/src/providers/auth0/provider.ts @@ -220,6 +220,7 @@ export const createAuth0Provider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -231,7 +232,7 @@ export const createAuth0Provider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/aws-alb/provider.ts b/plugins/auth-backend/src/providers/aws-alb/provider.ts index cc111b4aaf..12f7c7f4b4 100644 --- a/plugins/auth-backend/src/providers/aws-alb/provider.ts +++ b/plugins/auth-backend/src/providers/aws-alb/provider.ts @@ -241,7 +241,7 @@ export type AwsAlbProviderOptions = { export const createAwsAlbProvider = ( options?: AwsAlbProviderOptions, ): AuthProviderFactory => { - return ({ config, tokenIssuer, catalogApi, logger }) => { + return ({ config, tokenIssuer, catalogApi, logger, tokenManager }) => { const region = config.getString('region'); const issuer = config.getOptionalString('iss'); @@ -253,7 +253,7 @@ export const createAwsAlbProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/bitbucket/provider.ts b/plugins/auth-backend/src/providers/bitbucket/provider.ts index ff203e0a9d..4d5bdcf6f6 100644 --- a/plugins/auth-backend/src/providers/bitbucket/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucket/provider.ts @@ -273,6 +273,7 @@ export const createBitbucketProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -283,7 +284,7 @@ export const createBitbucketProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = diff --git a/plugins/auth-backend/src/providers/gcp-iap/provider.ts b/plugins/auth-backend/src/providers/gcp-iap/provider.ts index a54c7e9fb2..7816f68b76 100644 --- a/plugins/auth-backend/src/providers/gcp-iap/provider.ts +++ b/plugins/auth-backend/src/providers/gcp-iap/provider.ts @@ -102,7 +102,7 @@ export class GcpIapProvider implements AuthProviderRouteHandlers { export function createGcpIapProvider( options: GcpIapProviderOptions, ): AuthProviderFactory { - return ({ config, tokenIssuer, catalogApi, logger }) => { + return ({ config, tokenIssuer, catalogApi, logger, tokenManager }) => { const audience = config.getString('audience'); const authHandler = options.authHandler ?? defaultAuthHandler; @@ -111,7 +111,7 @@ export function createGcpIapProvider( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); return new GcpIapProvider({ diff --git a/plugins/auth-backend/src/providers/github/provider.ts b/plugins/auth-backend/src/providers/github/provider.ts index bef1a87b0a..9dc70cf60e 100644 --- a/plugins/auth-backend/src/providers/github/provider.ts +++ b/plugins/auth-backend/src/providers/github/provider.ts @@ -245,6 +245,7 @@ export const createGithubProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -270,7 +271,7 @@ export const createGithubProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/gitlab/provider.ts b/plugins/auth-backend/src/providers/gitlab/provider.ts index 5454065847..da816f2fd2 100644 --- a/plugins/auth-backend/src/providers/gitlab/provider.ts +++ b/plugins/auth-backend/src/providers/gitlab/provider.ts @@ -227,6 +227,7 @@ export const createGitlabProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -239,7 +240,7 @@ export const createGitlabProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 44c22f757e..13c5093aa5 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -259,6 +259,7 @@ export const createGoogleProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -269,7 +270,7 @@ export const createGoogleProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index b4ef30f491..9249f643dc 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -267,6 +267,7 @@ export const createMicrosoftProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -281,7 +282,7 @@ export const createMicrosoftProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts index eceebc5924..24bb4d0362 100644 --- a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts @@ -182,12 +182,12 @@ export const createOauth2ProxyProvider = ( options: Oauth2ProxyProviderOptions, ): AuthProviderFactory => - ({ catalogApi, logger, tokenIssuer }) => { + ({ catalogApi, logger, tokenIssuer, tokenManager }) => { const signInResolver = options.signIn.resolver; const authHandler = options.authHandler; const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); return new Oauth2ProxyAuthProvider({ logger, diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts index ec777c231b..8e69a3ee1d 100644 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2/provider.ts @@ -233,6 +233,7 @@ export const createOAuth2Provider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -249,7 +250,7 @@ export const createOAuth2Provider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts index 0c820648e4..fa46294784 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.ts @@ -257,6 +257,7 @@ export const createOidcProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -272,7 +273,7 @@ export const createOidcProvider = ( const prompt = envConfig.getOptionalString('prompt'); const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts index 30dd295d12..def0da694e 100644 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ b/plugins/auth-backend/src/providers/okta/provider.ts @@ -268,6 +268,7 @@ export const createOktaProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -286,7 +287,7 @@ export const createOktaProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = _options?.authHandler diff --git a/plugins/auth-backend/src/providers/onelogin/provider.ts b/plugins/auth-backend/src/providers/onelogin/provider.ts index ea84b402d5..a5ab4f658b 100644 --- a/plugins/auth-backend/src/providers/onelogin/provider.ts +++ b/plugins/auth-backend/src/providers/onelogin/provider.ts @@ -219,6 +219,7 @@ export const createOneLoginProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => @@ -230,7 +231,7 @@ export const createOneLoginProvider = ( const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/saml/provider.ts b/plugins/auth-backend/src/providers/saml/provider.ts index b9c8d89f5b..1ca8cf0d5d 100644 --- a/plugins/auth-backend/src/providers/saml/provider.ts +++ b/plugins/auth-backend/src/providers/saml/provider.ts @@ -187,12 +187,13 @@ export const createSamlProvider = ( globalConfig, config, tokenIssuer, + tokenManager, catalogApi, logger, }) => { const catalogIdentityClient = new CatalogIdentityClient({ catalogApi, - tokenIssuer, + tokenManager, }); const authHandler: AuthHandler = options?.authHandler diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 179d536f3c..b02e8d74b8 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { + PluginEndpointDiscovery, + TokenManager, +} from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; @@ -124,6 +127,7 @@ export type AuthProviderFactoryOptions = { globalConfig: AuthProviderConfig; config: Config; logger: Logger; + tokenManager: TokenManager; tokenIssuer: TokenIssuer; discovery: PluginEndpointDiscovery; catalogApi: CatalogApi; diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 6fdd768498..bdb68929b1 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -25,6 +25,7 @@ import { import { PluginDatabaseManager, PluginEndpointDiscovery, + TokenManager, } from '@backstage/backend-common'; import { assertError, NotFoundError } from '@backstage/errors'; import { CatalogClient } from '@backstage/catalog-client'; @@ -41,13 +42,21 @@ export interface RouterOptions { database: PluginDatabaseManager; config: Config; discovery: PluginEndpointDiscovery; + tokenManager: TokenManager; providerFactories?: ProviderFactories; } export async function createRouter( options: RouterOptions, ): Promise { - const { logger, config, discovery, database, providerFactories } = options; + const { + logger, + config, + discovery, + database, + tokenManager, + providerFactories, + } = options; const router = Router(); const appUrl = config.getString('app.baseUrl'); @@ -105,6 +114,7 @@ export async function createRouter( globalConfig: { baseUrl: authUrl, appUrl, isOriginAllowed }, config: providersConfig.getConfig(providerId), logger, + tokenManager, tokenIssuer, discovery, catalogApi, diff --git a/plugins/auth-backend/src/service/standaloneServer.ts b/plugins/auth-backend/src/service/standaloneServer.ts index 15ffe1d053..4e416e8dc7 100644 --- a/plugins/auth-backend/src/service/standaloneServer.ts +++ b/plugins/auth-backend/src/service/standaloneServer.ts @@ -17,6 +17,7 @@ import { createServiceBuilder, loadBackendConfig, + ServerTokenManager, SingleHostDiscovery, useHotMemoize, } from '@backstage/backend-common'; @@ -58,6 +59,7 @@ export async function startStandaloneServer( }, }, discovery, + tokenManager: ServerTokenManager.noop(), }); const service = createServiceBuilder(module)