diff --git a/.changeset/eight-files-rhyme.md b/.changeset/eight-files-rhyme.md new file mode 100644 index 0000000000..c45556366d --- /dev/null +++ b/.changeset/eight-files-rhyme.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-badges': minor +'@backstage/plugin-badges-backend': patch +--- + +Support auth in badge plugin diff --git a/plugins/badges-backend/src/service/router.ts b/plugins/badges-backend/src/service/router.ts index bfbb10fc94..8548476f5f 100644 --- a/plugins/badges-backend/src/service/router.ts +++ b/plugins/badges-backend/src/service/router.ts @@ -46,7 +46,12 @@ export async function createRouter( router.get('/entity/:namespace/:kind/:name/badge-specs', async (req, res) => { const { namespace, kind, name } = req.params; - const entity = await catalog.getEntityByName({ namespace, kind, name }); + const entity = await catalog.getEntityByName( + { namespace, kind, name }, + { + token: getBearerToken(req.headers.authorization), + }, + ); if (!entity) { throw new NotFoundError( `No ${kind} entity in ${namespace} named "${name}"`, @@ -81,7 +86,12 @@ export async function createRouter( '/entity/:namespace/:kind/:name/badge/:badgeId', async (req, res) => { const { namespace, kind, name, badgeId } = req.params; - const entity = await catalog.getEntityByName({ namespace, kind, name }); + const entity = await catalog.getEntityByName( + { namespace, kind, name }, + { + token: getBearerToken(req.headers.authorization), + }, + ); if (!entity) { throw new NotFoundError( `No ${kind} entity in ${namespace} named "${name}"`, @@ -134,3 +144,7 @@ async function getBadgeUrl( const baseUrl = await options.discovery.getExternalBaseUrl('badges'); return `${baseUrl}/entity/${namespace}/${kind}/${name}/badge/${badgeId}`; } + +function getBearerToken(header?: string): string | undefined { + return header?.match(/Bearer\s+(\S+)/i)?.[1]; +} diff --git a/plugins/badges/src/api/BadgesClient.ts b/plugins/badges/src/api/BadgesClient.ts index 927a16a7eb..c015a59703 100644 --- a/plugins/badges/src/api/BadgesClient.ts +++ b/plugins/badges/src/api/BadgesClient.ts @@ -15,7 +15,7 @@ */ import { generatePath } from 'react-router'; -import { DiscoveryApi } from '@backstage/core'; +import { DiscoveryApi, IdentityApi } from '@backstage/core'; import { ResponseError } from '@backstage/errors'; import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { entityRoute } from '@backstage/plugin-catalog-react'; @@ -23,14 +23,26 @@ import { BadgesApi, BadgeSpec } from './types'; export class BadgesClient implements BadgesApi { private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; - constructor(options: { discoveryApi: DiscoveryApi }) { + constructor(options: { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + }) { this.discoveryApi = options.discoveryApi; + this.identityApi = options.identityApi; } public async getEntityBadgeSpecs(entity: Entity): Promise { const entityBadgeSpecsUrl = await this.getEntityBadgeSpecsUrl(entity); - const response = await fetch(entityBadgeSpecsUrl); + const token = await this.identityApi.getIdToken(); + const response = await fetch(entityBadgeSpecsUrl, { + headers: token + ? { + Authorization: `Bearer ${token}`, + } + : undefined, + }); if (!response.ok) { throw await ResponseError.fromResponse(response); diff --git a/plugins/badges/src/plugin.ts b/plugins/badges/src/plugin.ts index 92932aa356..a247c93a4b 100644 --- a/plugins/badges/src/plugin.ts +++ b/plugins/badges/src/plugin.ts @@ -18,6 +18,7 @@ import { createComponentExtension, createPlugin, discoveryApiRef, + identityApiRef, } from '@backstage/core'; import { badgesApiRef, BadgesClient } from './api'; @@ -26,8 +27,9 @@ export const badgesPlugin = createPlugin({ apis: [ createApiFactory({ api: badgesApiRef, - deps: { discoveryApi: discoveryApiRef }, - factory: ({ discoveryApi }) => new BadgesClient({ discoveryApi }), + deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, + factory: ({ discoveryApi, identityApi }) => + new BadgesClient({ discoveryApi, identityApi }), }), ], });