fix: update docs with new approach and export types

Signed-off-by: Juan Pablo Garcia Ripa <sarabadu@gmail.com>
This commit is contained in:
Juan Pablo Garcia Ripa
2025-05-15 22:58:35 +02:00
parent 410b81afd7
commit 65d382e272
5 changed files with 67 additions and 34 deletions
+28 -7
View File
@@ -414,7 +414,7 @@ Each entry has one or more of the following fields:
## Adding custom or logic for validation and issuing of tokens
The `pluginTokenHandlerDecoratorServiceRef` and `externalTokenHandlersServiceRef` can be used to extend the existing token handler without having to re-implement the entire `AuthService` implementation.
The `pluginTokenHandlerDecoratorServiceRef` and `externalTokenTypeHandlersRef` can be used to extend the existing token handler without having to re-implement the entire `AuthService` implementation.
This is particularly useful when you want to add additional logic to the handler, such as logging or metrics or custom token validation.
### PluginTokenHandler decoration
@@ -446,26 +446,47 @@ const decoratedPluginTokenHandler = createServiceFactory({
### ExternalTokenHandler decoration
The `externalTokenHandlersServiceRef` can be used to add custom external token handlers to the default implementation.
The `externalTokenTypeHandlersRef` can be used to add custom external token handlers to the default implementation.
The returned object should be a map of token custom types and their handler factories. The object keys will be matched to the configured `externalAccess` type in the app-config, calling the factory function with the config object for that type. Custom token handlers should implement the `TokenHandler` interface, which provides methods for verifying tokens.
The returned object from the factory function must have a `type` property which is used to identify the handler. The `factory` method is called with an array of `Config` objects, for the given type. The factory method can return a single handler or an array of handlers. The handlers are then used to handle the token for the given type.
For example, to add a custom token handler for a type called 'custom':
For example, if we whant to add a custom external token handler for the `custom` type:
our config would look like this:
```yaml title="in e.g. app-config.production.yaml"
backend:
auth:
externalAccess:
- type: custom
options:
customOptions: additional-value
accessRestrictions:
- plugin: events
- type: custom
options:
customOptions: another-value
accessRestrictions:
- plugin: events
```
And we can implement the custom token handler like this:
```ts
import {
TokenHandler,
externalTokenHandlersServiceRef,
externalTokenTypeHandlersRef,
} from '@backstage/backend-defaults/auth';
import { Config } from '@backstage/config';
import { createServiceFactory } from '@backstage/backend-plugin-api';
const customExternalTokenHandlers = createServiceFactory({
service: externalTokenHandlersServiceRef,
service: externalTokenTypeHandlersRef,
deps: {},
async factory() {
return {
custom: (config: Config) => new CustomTokenHandler(config);
type: 'custom',
factory: (configs: Config[]) => new CustomTokenHandler(configs), // can return a simple handler or an array of handlers
};
},
});
+8 -4
View File
@@ -24,10 +24,7 @@ export const authServiceFactory: ServiceFactory<
// @public
export const externalTokenTypeHandlersRef: ServiceRef<
{
type: string;
factory: (config: Config[]) => TokenHandler;
},
TokenTypeHandler,
'plugin',
'multiton'
>;
@@ -74,5 +71,12 @@ export interface TokenHandler {
>;
}
// @public
export interface TokenTypeHandler {
factory: (configs: Config[]) => TokenHandler | TokenHandler[];
// (undocumented)
type: string;
}
// (No @packageDocumentation comment for this package)
```
@@ -27,32 +27,12 @@ import { JWKSHandler } from './jwks';
import { TokenHandler } from './types';
import { Config } from '@backstage/config';
import { groupBy } from 'lodash';
import { TokenTypeHandler } from './types';
const NEW_CONFIG_KEY = 'backend.auth.externalAccess';
const OLD_CONFIG_KEY = 'backend.auth.keys';
let loggedDeprecationWarning = false;
/**
* @public
* This service is used to decorate the default plugin token handler with custom logic.
*/
export const externalTokenTypeHandlersRef = createServiceRef<{
type: string;
factory: (config: Config[]) => TokenHandler;
}>({
id: 'core.auth.externalTokenHandlers',
multiton: true,
// defaultFactory // :pepe-think: seems like is not possible to use defaultFactory with multiton
});
type TokenTypeHandler = {
type: string;
/**
* A factory function that takes all token configuration for a given type
* and returns a TokenHandler or an array of TokenHandlers.
*/
factory: (config: Config[]) => TokenHandler | TokenHandler[];
};
type LegacyTokenTypeHandler = {
type: 'legacy';
/**
@@ -60,10 +40,23 @@ type LegacyTokenTypeHandler = {
* and returns a TokenHandler or an array of TokenHandlers.
*/
factory: (
config: (Config | LegacyConfigWrapper)[],
configs: (
| import('@backstage/config').Config
| { legacy: true; config: import('@backstage/config').Config }
)[],
) => TokenHandler | TokenHandler[];
};
/**
* @public
* This service is used to decorate the default plugin token handler with custom logic.
*/
export const externalTokenTypeHandlersRef = createServiceRef<TokenTypeHandler>({
id: 'core.auth.externalTokenHandlers',
multiton: true,
// defaultFactory // :pepe-think: seems like is not possible to use defaultFactory with multiton
});
const defaultHandlers: (TokenTypeHandler | LegacyTokenTypeHandler)[] = [
{
type: 'static',
@@ -38,3 +38,18 @@ export interface TokenHandler {
| undefined
>;
}
/**
* @public
* This interface is used to handle external tokens.
*/
export interface TokenTypeHandler {
type: string;
/**
* A factory function that takes all token configuration for a given type
* and returns a TokenHandler or an array of TokenHandlers.
*/
factory: (
configs: import('@backstage/config').Config[],
) => TokenHandler | TokenHandler[];
}
@@ -21,7 +21,7 @@ export {
export { externalTokenTypeHandlersRef } from './external/ExternalTokenHandler';
export type { TokenHandler } from './external/types';
export type { TokenHandler, TokenTypeHandler } from './external/types';
export type { AccessRestrictionsMap } from './external/types';
export type { PluginTokenHandler } from './plugin/PluginTokenHandler';