backend-app-api,auth: move token typ claim to be a header param
Co-authored-by: Camila Belo <camilaibs@gmail.com> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
committed by
Camila Belo
parent
018b0910e0
commit
0d2a05418b
@@ -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<TPrincipal = unknown> =
|
||||
@@ -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<BackstageCredentials> {
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user