diff --git a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts b/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts index 39dd88aafa..2f75847608 100644 --- a/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/auth/authServiceFactory.ts @@ -22,16 +22,13 @@ import { BackstageServicePrincipal, BackstageNonePrincipal, BackstageUserPrincipal, - IdentityService, coreServices, createServiceFactory, } from '@backstage/backend-plugin-api'; import { AuthenticationError } from '@backstage/errors'; -import { - IdentityApiGetIdentityRequest, - TokenTypes, -} from '@backstage/plugin-auth-node'; -import { base64url, decodeJwt } from 'jose'; +import { TokenTypes } from '@backstage/plugin-auth-node'; +import { base64url, decodeJwt, decodeProtectedHeader } from 'jose'; +import { UserTokenHandler } from './UserTokenHandler'; /** @internal */ export type InternalBackstageCredentials = @@ -115,7 +112,8 @@ class DefaultAuthService implements AuthService { // allowLimitedAccess is currently ignored, since we currently always use the full user tokens async authenticate(token: string): Promise { - const { typ, sub, aud } = decodeJwt(token); + const { typ } = decodeProtectedHeader(token); + const { sub, aud } = decodeJwt(token); if (typ) { switch (typ) { @@ -244,13 +242,13 @@ class DefaultAuthService implements AuthService { const limitedUserToken = [ base64url.encode( JSON.stringify({ + typ: 'vnd.backstage.limited-user', alg: header.alg, kid: header.kid, }), ), base64url.encode( JSON.stringify({ - typ: 'vnd.backstage.limited-user', sub: payload.sub, ent: payload.ent, iat: payload.iat, diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index b89225eca5..1e440a5695 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -115,14 +115,17 @@ export class TokenFactory implements TokenIssuer { const signingKey = await importJWK(key); const uip = await this.createUserIdentityClaim({ - header: { alg: key.alg, kid: key.kid }, - payload: { typ: TokenTypes.limitedUser.typClaim, sub, ent, iat, exp }, + header: { + typ: TokenTypes.limitedUser.typParam, + alg: key.alg, + kid: key.kid, + }, + payload: { sub, ent, iat, exp }, key: signingKey, }); const claims: BackstageTokenPayload = { ...additionalClaims, - typ: TokenTypes.user.typClaim, iss, sub, ent, @@ -133,7 +136,11 @@ export class TokenFactory implements TokenIssuer { }; const token = await new SignJWT(claims) - .setProtectedHeader({ alg: key.alg, kid: key.kid }) + .setProtectedHeader({ + typ: TokenTypes.user.typParam, + alg: key.alg, + kid: key.kid, + }) .sign(signingKey); if (token.length > MAX_TOKEN_LENGTH) { @@ -243,6 +250,7 @@ export class TokenFactory implements TokenIssuer { // JWS. private async createUserIdentityClaim(options: { header: { + typ: string; alg: string; kid?: string; }; @@ -257,12 +265,12 @@ export class TokenFactory implements TokenIssuer { // then append the signature. const header = { + typ: options.header.typ, alg: options.header.alg, ...(options.header.kid ? { kid: options.header.kid } : {}), }; const payload = { - typ: options.payload.typ, sub: options.payload.sub, ent: options.payload.ent, iat: options.payload.iat, diff --git a/plugins/auth-node/src/types.ts b/plugins/auth-node/src/types.ts index fe84da38a4..8fdb91845d 100644 --- a/plugins/auth-node/src/types.ts +++ b/plugins/auth-node/src/types.ts @@ -383,14 +383,14 @@ export type CookieConfigurer = (ctx: { */ export const TokenTypes = Object.freeze({ user: Object.freeze({ - typClaim: 'vnd.backstage.user', + typParam: 'vnd.backstage.user', audClaim: 'backstage', }), limitedUser: Object.freeze({ - typClaim: 'vnd.backstage.limited-user', + typParam: 'vnd.backstage.limited-user', }), service: Object.freeze({ - typClaim: 'vnd.backstage.service', + typParam: 'vnd.backstage.service', }), }); @@ -400,11 +400,6 @@ export const TokenTypes = Object.freeze({ * @public */ export interface BackstageTokenPayload { - /** - * The token type - */ - typ: typeof TokenTypes.user.typClaim; - /** * The issuer of the token, currently the discovery URL of the auth backend */ @@ -452,11 +447,6 @@ export interface BackstageTokenPayload { * @public */ export interface BackstageUserIdentityProofPayload { - /** - * The token type - */ - typ: typeof TokenTypes.limitedUser.typClaim; - /** * The entity ref of the user */