backend-app-api: stop requiring keys to be configured for the token manager

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2024-04-20 16:16:48 +02:00
parent ba0b8b45da
commit dc8c5ddbae
4 changed files with 25 additions and 18 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-app-api': patch
---
The default `TokenManager` implementation no longer requires keys to be configured in production, but it will throw an errors when generating or authenticating tokens. The default `AuthService` implementation will now also provide additional context if such an error is throw when falling back to using the `TokenManager` service to generate tokens for outgoing requests.
@@ -23,7 +23,7 @@ import {
BackstageServicePrincipal,
BackstageUserPrincipal,
} from '@backstage/backend-plugin-api';
import { AuthenticationError } from '@backstage/errors';
import { AuthenticationError, ForwardedError } from '@backstage/errors';
import { JsonObject } from '@backstage/types';
import { decodeJwt } from 'jose';
import { ExternalTokenHandler } from './external/ExternalTokenHandler';
@@ -151,7 +151,13 @@ export class DefaultAuthService implements AuthService {
});
}
// If the target plugin does not support the new auth service, fall back to using old token format
return this.tokenManager.getToken();
return this.tokenManager.getToken().catch(error => {
throw new ForwardedError(
`Unable to generate legacy token for communication with the '${targetPluginId}' plugin. ` +
`You will typically encounter this error when attempting to call a plugin that does not exist, or is deployed with an old version of Backstage`,
error,
);
});
case 'user': {
const { token } = internalForward;
if (!token) {
@@ -14,25 +14,20 @@
* limitations under the License.
*/
import { LoggerService } from '@backstage/backend-plugin-api';
import { ConfigReader } from '@backstage/config';
import { tokenManagerServiceFactory } from './tokenManagerServiceFactory';
import { ServiceFactoryTester } from '@backstage/backend-test-utils';
describe('tokenManagerFactory', () => {
it('should create managers that can share tokens in development', async () => {
(process.env as { NODE_ENV?: string }).NODE_ENV = 'development';
it('should create a disabled manager without configuration', async () => {
const tokenManager = await ServiceFactoryTester.from(
tokenManagerServiceFactory,
).get();
const factory = tokenManagerServiceFactory() as any;
const deps = {
config: new ConfigReader({}),
logger: { warn() {} } as unknown as LoggerService,
};
const ctx = await factory.createRootContext?.(deps);
const manager1 = await factory.factory!(deps, ctx);
const manager2 = await factory.factory!(deps, ctx);
const { token } = await manager1.getToken();
await expect(manager2.authenticate(token)).resolves.toBeUndefined();
await expect(tokenManager.authenticate('abc')).rejects.toThrow(
'no legacy keys are configured',
);
await expect(tokenManager.getToken()).rejects.toThrow(
'no legacy keys are configured',
);
});
});
@@ -30,6 +30,7 @@ export const tokenManagerServiceFactory = createServiceFactory({
createRootContext({ config, logger }) {
return ServerTokenManager.fromConfig(config, {
logger,
allowDisabledTokenManager: true,
});
},
async factory(_deps, tokenManager) {