diff --git a/plugins/auth-backend/src/identity/TokenFactory.test.ts b/plugins/auth-backend/src/identity/TokenFactory.test.ts index 9a163b3ff5..4f6df89210 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.test.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.test.ts @@ -48,7 +48,12 @@ describe('TokenFactory', () => { await expect(factory.listPublicKeys()).resolves.toEqual({ keys: [] }); const token = await factory.issueToken({ - claims: { sub: entityRef, ent: [entityRef] }, + claims: { + sub: entityRef, + ent: [entityRef], + 'x-fancy-claim': 'my special claim', + aud: 'this value will be overridden', + }, }); const { keys } = await factory.listPublicKeys(); @@ -60,6 +65,7 @@ describe('TokenFactory', () => { aud: 'backstage', sub: entityRef, ent: [entityRef], + 'x-fancy-claim': 'my special claim', iat: expect.any(Number), exp: expect.any(Number), }); diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index 44cfebfb71..f80b79b6bc 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -77,8 +77,7 @@ export class TokenFactory implements TokenIssuer { const key = await this.getKey(); const iss = this.issuer; - const sub = params.claims.sub; - const ent = params.claims.ent; + const { sub, ent, ...additionalClaims } = params.claims; const aud = 'backstage'; const iat = Math.floor(Date.now() / MS_IN_S); const exp = iat + this.keyDurationSeconds; @@ -98,7 +97,7 @@ export class TokenFactory implements TokenIssuer { throw new AuthenticationError('No algorithm was provided in the key'); } - return new SignJWT({ iss, sub, ent, aud, iat, exp }) + return new SignJWT({ ...additionalClaims, iss, sub, ent, aud, iat, exp }) .setProtectedHeader({ alg: key.alg, kid: key.kid }) .setIssuer(iss) .setAudience(aud) diff --git a/plugins/auth-backend/src/identity/types.ts b/plugins/auth-backend/src/identity/types.ts index 4765b50d7d..49d78b8472 100644 --- a/plugins/auth-backend/src/identity/types.ts +++ b/plugins/auth-backend/src/identity/types.ts @@ -28,13 +28,19 @@ export interface AnyJWK extends Record { * @public */ export type TokenParams = { - /** The claims that will be embedded within the token */ + /** + * The claims that will be embedded within the token. At a minimum, this should include + * the subject claim, `sub`. It is common to also list entity ownership relations in the + * `ent` list. Additional claims may also be added at the developer's discretion except + * for the following list, which will be overwritten by the TokenIssuer: `iss`, `aud`, + * `iat`, and `exp`. + */ claims: { /** The token subject, i.e. User ID */ sub: string; /** A list of entity references that the user claims ownership through */ ent?: string[]; - }; + } & Record; }; /**