From 750fca110d7179626444f02e4b66b3aa5fe8fe5e Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 13 Feb 2024 10:56:56 +0100 Subject: [PATCH] chore: fix the middleware Signed-off-by: blam --- .changeset/curvy-icons-peel.md | 2 +- plugins/badges-backend/src/service/router.ts | 56 +++++++++++++++----- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/.changeset/curvy-icons-peel.md b/.changeset/curvy-icons-peel.md index ccd8337bea..bbadcb0a55 100644 --- a/.changeset/curvy-icons-peel.md +++ b/.changeset/curvy-icons-peel.md @@ -2,4 +2,4 @@ '@backstage/plugin-badges-backend': patch --- -Removing the authentication middleware from the obfuscated routes, as it doesn't do what it's supposed to do. +Updating the `authorization` middleware to call the Catalog to check that the requesting user has permission to see the Entity before generating the UUID. diff --git a/plugins/badges-backend/src/service/router.ts b/plugins/badges-backend/src/service/router.ts index 0223e2e84d..0c5e19d0e8 100644 --- a/plugins/badges-backend/src/service/router.ts +++ b/plugins/badges-backend/src/service/router.ts @@ -24,12 +24,13 @@ import { } from '@backstage/backend-common'; import { CatalogApi, CatalogClient } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; -import { NotFoundError } from '@backstage/errors'; +import { AuthenticationError, NotFoundError } from '@backstage/errors'; import { BadgeBuilder, DefaultBadgeBuilder } from '../lib/BadgeBuilder'; import { BadgeContext, BadgeFactories } from '../types'; import { isNil } from 'lodash'; import { Logger } from 'winston'; import { IdentityApi } from '@backstage/plugin-auth-node'; +import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { BadgesStore, DatabaseBadgesStore } from '../database/badgesStore'; import { createDefaultBadgeFactories } from '../badges'; @@ -214,19 +215,50 @@ async function obfuscatedRoute( res.status(200).send(data); }); - router.get('/entity/:namespace/:kind/:name/obfuscated', async (req, res) => { - const { namespace, kind, name } = req.params; - const storedEntityUuid: { uuid: string } | undefined = - await store.getBadgeUuid(name, namespace, kind); - - if (isNil(storedEntityUuid)) { - throw new NotFoundError( - `No uuid found for entity "${namespace}/${kind}/${name}"`, + router.get( + '/entity/:namespace/:kind/:name/obfuscated', + async function authenticate(req, _res, next) { + const token = getBearerTokenFromAuthorizationHeader( + req.headers.authorization, ); - } - return res.status(200).json(storedEntityUuid); - }); + const { kind, namespace, name } = req.params; + + // check that the user has the correct permissions + // to view the catalog entity by forwarding the token + const entity = await catalog.getEntityByRef( + { + kind, + namespace, + name, + }, + { token }, + ); + + if (!entity) { + next( + new NotFoundError( + `No ${kind} entity in ${namespace} named "${name}"`, + ), + ); + } else { + next(); + } + }, + async (req, res) => { + const { namespace, kind, name } = req.params; + const storedEntityUuid: { uuid: string } | undefined = + await store.getBadgeUuid(name, namespace, kind); + + if (isNil(storedEntityUuid)) { + throw new NotFoundError( + `No uuid found for entity "${namespace}/${kind}/${name}"`, + ); + } + + return res.status(200).json(storedEntityUuid); + }, + ); router.use(errorHandler());