chore: Add documentation

Signed-off-by: Johan Haals <johan.haals@gmail.com>
This commit is contained in:
Johan Haals
2024-11-22 10:02:54 +01:00
parent 3052ecd97d
commit 062eaf3f75
3 changed files with 49 additions and 4 deletions
+45
View File
@@ -412,3 +412,48 @@ Each entry has one or more of the following fields:
# Also supports the shorthand form:
# action: create, read
```
## Adding custom or logic for validation and issuing of tokens
The `pluginTokenHandlerDecoratorServiceRef` can be used to decorate the existing token handler without having to re-implement the entire `PluginTokenHandler`.
This is particularly useful when you want to add additional logic to the handler, such as logging or metrics or custom token validation.
The `PluginTokenHandler` interface has two methods:
- `issueToken`: This method is used to issue a token for a plugin. It takes in the `pluginId` and `targetPluginId` as arguments, and an optional `limitedUserToken` object which can be used to issue a token on behalf of another user. The method returns a promise that resolves to an object containing the issued token.
- `verifyToken`: This method is used to verify a token. It takes in the token as an argument and returns a promise that resolves to an object containing the subject of the token and an optional limited user token.
```ts
import {
PluginTokenHandler,
pluginTokenHandlerDecoratorServiceRef,
} from '@backstage/backend-defaults/auth';
import { createServiceFactory } from '@backstage/backend-plugin-api';
const decoratedPluginTokenHandler = createServiceFactory({
service: pluginTokenHandlerDecoratorServiceRef,
deps: {},
async factory() {
return (defaultImplementation: PluginTokenHandler) =>
new (class CustomHandler implements PluginTokenHandler {
verifyToken(
token: string,
): Promise<{ subject: string; limitedUserToken?: string } | undefined> {
// custom logic here
if (isMyCustomToken(token)) {
return { subject: 'custom-subject' };
}
return defaultImplementation.verifyToken(token);
}
issueToken(options: {
pluginId: string;
targetPluginId: string;
limitedUserToken?: { token: string; expiresAt: Date };
}): Promise<{ token: string }> {
return defaultImplementation.issueToken(options);
}
})();
},
});
```
@@ -428,7 +428,6 @@ describe('authServiceFactory', () => {
{ subject: string; limitedUserToken?: string } | undefined
> {
customLogic(token);
// check if token is iam/auth or basicAuth, verify.
return defaultImplementation.verifyToken(token);
}
issueToken(options: {
@@ -16,7 +16,7 @@
import { DiscoveryService, LoggerService } from '@backstage/backend-plugin-api';
import { decodeJwt, importJWK, SignJWT, decodeProtectedHeader } from 'jose';
import { AuthenticationError } from '@backstage/errors';
import { assertError, AuthenticationError } from '@backstage/errors';
import { jwtVerify } from 'jose';
import { tokenTypes } from '@backstage/plugin-auth-node';
import { JwksClient } from '../JwksClient';
@@ -46,7 +46,7 @@ type Options = {
/**
* @public
* Issues and verifies {@link https://backstage.io/docs/auth/service-to-service-auth | service-to-service tokens}.
* Issues and verifies {@link https://backstage.iceio/docs/auth/service-to-service-auth | service-to-service tokens}.
*/
export interface PluginTokenHandler {
verifyToken(
@@ -194,7 +194,8 @@ export class DefaultPluginTokenHandler implements PluginTokenHandler {
this.supportedTargetPlugins.add(targetPluginId);
return true;
} catch (error: any) {
} catch (error) {
assertError(error);
this.logger.error('Unexpected failure for target JWKS check', error);
return false;
} finally {