diff --git a/.changeset/few-vans-cross.md b/.changeset/few-vans-cross.md new file mode 100644 index 0000000000..d7a12f6c10 --- /dev/null +++ b/.changeset/few-vans-cross.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Plugins created through the `legacyPlugin` helper are now able to authenticate requests from plugins that are fully implemented using the new backend system. This fixes the `Key for the ES256 algorithm must be one of type KeyObject or CryptoKey. Received an instance of Uint8Array` error. diff --git a/packages/backend-common/src/legacy.ts b/packages/backend-common/src/legacy.ts index df1030e6b6..6aa991489c 100644 --- a/packages/backend-common/src/legacy.ts +++ b/packages/backend-common/src/legacy.ts @@ -15,6 +15,7 @@ */ import { + AuthService, coreServices, createBackendPlugin, ServiceRef, @@ -22,6 +23,7 @@ import { import { RequestHandler } from 'express'; import { cacheToPluginCacheManager } from './cache'; import { loggerToWinstonLogger } from './logging'; +import { TokenManager } from './tokens'; /** * @public @@ -38,6 +40,31 @@ type TransformedEnv< : TEnv[key]; }; +// Since the plugin will be using the new system our callers will expect us to support the +// new plugin tokens, which we'll also be signaling by supporting the JWKS endpoint through +// the http router. +// This makes sure that we accept the new plugin tokens as valid tokens, but otherwise fall +// back to whatever the token manager is doing. +function wrapTokenManager(tokenManager: TokenManager, auth: AuthService) { + return { + async getToken() { + return tokenManager.getToken(); + }, + async authenticate(token) { + if (token) { + // Unless it's a valid service token, we'll let the token manager do + // validation. We'll throw if we for example receive an invalid user + // token here, but that's what the token manager does too. + const credentials = await auth.authenticate(token); + if (auth.isPrincipal(credentials, 'service')) { + return; + } + } + await tokenManager.authenticate(token); + }, + } satisfies TokenManager; +} + /** * Creates a new custom plugin compatibility wrapper. * @@ -64,8 +91,12 @@ export function makeLegacyPlugin< pluginId: name, register(env) { env.registerInit({ - deps: { ...envMapping, _router: coreServices.httpRouter }, - async init({ _router, ...envDeps }) { + deps: { + ...envMapping, + _router: coreServices.httpRouter, + _auth: coreServices.auth, + }, + async init({ _router, _auth, ...envDeps }) { const { default: createRouter } = await createRouterImport; const pluginEnv = Object.fromEntries( Object.entries(envDeps).map(([key, dep]) => { @@ -73,6 +104,9 @@ export function makeLegacyPlugin< if (transform) { return [key, transform(dep)]; } + if (key === 'tokenManager') { + return [key, wrapTokenManager(dep as TokenManager, _auth)]; + } return [key, dep]; }), );