From 0d1ad9faf9e6b0006c43c922c0167f5a7521c720 Mon Sep 17 00:00:00 2001 From: Tyler Davis Date: Thu, 22 Feb 2024 17:20:17 +1100 Subject: [PATCH] PR feedback: change structure of serviceTokens config Signed-off-by: Tyler Davis --- docs/auth/cloudflare/access.md | 2 +- plugins/auth-backend/config.d.ts | 5 +++ .../providers/cloudflare-access/provider.ts | 32 +++++++++++-------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/docs/auth/cloudflare/access.md b/docs/auth/cloudflare/access.md index 7c5c5d51d4..17a37c6ef8 100644 --- a/docs/auth/cloudflare/access.md +++ b/docs/auth/cloudflare/access.md @@ -26,7 +26,7 @@ auth: cfaccess: teamName: serviceTokens: - "1uh2fh19efvfh129f1f919u21f2f19jf2.access": "bot-user@your-company.com" + '1uh2fh19efvfh129f1f919u21f2f19jf2.access': 'bot-user@your-company.com' ``` You can find the team name in the Cloudflare Zero Trust dashboard. diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index 4c8430b33f..0a1425c98b 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -185,6 +185,11 @@ export interface Config { /** @visibility frontend */ cfaccess?: { teamName: string; + /** @visibility secret */ + serviceTokens?: Array<{ + token: string; + subject: string; + }>; }; /** * The backstage token expiration. diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts index 31e6e6d391..e4d317f8f6 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts @@ -48,7 +48,10 @@ const CACHE_PREFIX = 'providers/cloudflare-access/profile-v1'; */ export const CF_DEFAULT_CACHE_TTL = 3600; -type ServiceTokens = Record; +type ServiceToken = { + token: string; + subject: string; +}; /** @public */ export type Options = { @@ -68,7 +71,7 @@ export type Options = { * the Client ID of any Service Tokens that should be allowed to pass the * auth check to the identity (email) you would like to associate with it. */ - serviceTokens: ServiceTokens; + serviceTokens: ServiceToken[]; authHandler: AuthHandler; signInResolver: SignInResolver; resolverContext: AuthResolverContext; @@ -189,7 +192,7 @@ export type CloudflareAccessResponse = export class CloudflareAccessAuthProvider implements AuthProviderRouteHandlers { private readonly teamName: string; - private readonly serviceTokens: ServiceTokens; + private readonly serviceTokens: ServiceToken[]; private readonly resolverContext: AuthResolverContext; private readonly authHandler: AuthHandler; private readonly signInResolver: SignInResolver; @@ -284,7 +287,8 @@ export class CloudflareAccessAuthProvider implements AuthProviderRouteHandlers { ); } - if (isServiceToken && !this.serviceTokens.hasOwnProperty(subject)) { + const serviceToken = this.serviceTokens.find(st => st.token === subject); + if (isServiceToken && !serviceToken) { throw new AuthenticationError( `${subject} is not a permitted Service Token.`, ); @@ -304,11 +308,11 @@ export class CloudflareAccessAuthProvider implements AuthProviderRouteHandlers { // Builds a passport profile from JWT claims first try { let cfIdentity: CloudflareAccessIdentityProfile; - if (isServiceToken) { + if (serviceToken) { cfIdentity = { id: subject, name: 'Bot', - email: this.serviceTokens[subject], + email: serviceToken.subject, groups: [], }; } else { @@ -391,13 +395,15 @@ export const cfAccess = createAuthProviderIntegration({ }) { return ({ config, resolverContext }) => { const teamName = config.getString('teamName'); - const serviceTokensConfig = config.getOptionalConfig('serviceTokens'); - const serviceTokens: ServiceTokens = {}; - if (serviceTokensConfig) { - serviceTokensConfig.keys().forEach(key => { - serviceTokens[key] = serviceTokensConfig.getString(key); - }); - } + const serviceTokensConfig = + config.getOptionalConfigArray('serviceTokens'); + const serviceTokens = + serviceTokensConfig?.map(cfg => { + return { + token: cfg.getString('token'), + subject: cfg.getString('subject'), + } as ServiceToken; + }) || []; if (!options.signIn.resolver) { throw new Error(