diff --git a/.changeset/smooth-garlics-behave.md b/.changeset/smooth-garlics-behave.md new file mode 100644 index 0000000000..ed972ae164 --- /dev/null +++ b/.changeset/smooth-garlics-behave.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Added option to `ServerTokenManager.fromConfig` that allows it to be instantiated in production without any configured keys. diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 888bc1639c..f9e0d76aab 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -772,7 +772,7 @@ export class ServerTokenManager implements TokenManager { static fromConfig( config: Config, options: ServerTokenManagerOptions, - ): ServerTokenManager; + ): TokenManager; // (undocumented) getToken(): Promise<{ token: string; @@ -782,6 +782,7 @@ export class ServerTokenManager implements TokenManager { // @public export interface ServerTokenManagerOptions { + allowDisabledTokenManager?: boolean; logger: LoggerService; } diff --git a/packages/backend-common/src/tokens/ServerTokenManager.test.ts b/packages/backend-common/src/tokens/ServerTokenManager.test.ts index 7b9cf5965f..8870b4ed1c 100644 --- a/packages/backend-common/src/tokens/ServerTokenManager.test.ts +++ b/packages/backend-common/src/tokens/ServerTokenManager.test.ts @@ -301,6 +301,20 @@ describe('ServerTokenManager', () => { ), ).toThrow(); }); + + it('should throw errors when disabled', async () => { + const manager = ServerTokenManager.fromConfig(new ConfigReader({}), { + logger, + allowDisabledTokenManager: true, + }); + + await expect(manager.getToken()).rejects.toThrow( + 'Unable to generate legacy token', + ); + await expect(manager.authenticate('nah')).rejects.toThrow( + 'Unable to authenticate legacy token', + ); + }); }); describe('NODE_ENV === development', () => { diff --git a/packages/backend-common/src/tokens/ServerTokenManager.ts b/packages/backend-common/src/tokens/ServerTokenManager.ts index 453bfd7228..a62eb8de55 100644 --- a/packages/backend-common/src/tokens/ServerTokenManager.ts +++ b/packages/backend-common/src/tokens/ServerTokenManager.ts @@ -40,6 +40,23 @@ class NoopTokenManager implements TokenManager { async authenticate() {} } +/** + * A token manager that throws an error when trying to generate or authenticate tokens. + */ +class DisabledTokenManager implements TokenManager { + async getToken(): Promise<{ token: string }> { + throw new Error( + "Unable to generate legacy token, no legacy keys are configured in 'backend.auth.keys' or 'backend.auth.externalAccess'", + ); + } + + async authenticate() { + throw new AuthenticationError( + "Unable to authenticate legacy token, no legacy keys are configured in 'backend.auth.keys' or 'backend.auth.externalAccess'", + ); + } +} + /** * Options for {@link ServerTokenManager}. * @@ -50,6 +67,11 @@ export interface ServerTokenManagerOptions { * The logger to use. */ logger: LoggerService; + + /** + * Whether to disable the token manager if no keys are configured. + */ + allowDisabledTokenManager?: boolean; } /** @@ -73,7 +95,10 @@ export class ServerTokenManager implements TokenManager { return new NoopTokenManager(); } - static fromConfig(config: Config, options: ServerTokenManagerOptions) { + static fromConfig( + config: Config, + options: ServerTokenManagerOptions, + ): TokenManager { const oldSecrets = config .getOptionalConfigArray('backend.auth.keys') ?.map(c => c.getString('secret')); @@ -87,6 +112,14 @@ export class ServerTokenManager implements TokenManager { return new ServerTokenManager(secrets, options); } + // When using the new backend system with new auth services we instead rely + // on the new plugin auth and external access configurations. If no legacy + // keys are configured we disable the token manager completely, rather than + // requiring users to configure legacy keys. + if (options.allowDisabledTokenManager) { + return new DisabledTokenManager(); + } + if (process.env.NODE_ENV !== 'development') { throw new Error( 'You must configure at least one key in backend.auth.keys for production.',