From e1ebaeb332fe8d8da4c3574e7c107930cb1d4556 Mon Sep 17 00:00:00 2001 From: Tyler Davis Date: Thu, 18 Aug 2022 15:00:52 +1000 Subject: [PATCH 1/6] Add the JWT to the CloudflareAccessResult Signed-off-by: Tyler Davis --- .changeset/rich-cooks-camp.md | 5 +++++ .../auth-backend/src/providers/cloudflare-access/provider.ts | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 .changeset/rich-cooks-camp.md diff --git a/.changeset/rich-cooks-camp.md b/.changeset/rich-cooks-camp.md new file mode 100644 index 0000000000..04d86033f7 --- /dev/null +++ b/.changeset/rich-cooks-camp.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Cloudflare Access Provider: Add JWT to CloudflareAccessResult diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts index a2c16fcebf..38205c9cff 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts @@ -153,6 +153,7 @@ export type CloudflareAccessResult = { claims: CloudflareAccessClaims; cfIdentity: CloudflareAccessIdentityProfile; expiresInSeconds?: number; + jwt: string; }; /** @@ -277,6 +278,7 @@ export class CloudflareAccessAuthProvider implements AuthProviderRouteHandlers { claims, cfIdentity, expiresInSeconds: claims.exp - claims.iat, + jwt, }; this.cache?.set(`${CACHE_PREFIX}/${sub}`, JSON.stringify(cfAccessResult)); return cfAccessResult; From 3b40d807475a5e43ab488dafdd357b0b5292e284 Mon Sep 17 00:00:00 2001 From: Tyler Davis Date: Fri, 19 Aug 2022 11:48:17 +1000 Subject: [PATCH 2/6] update API report Signed-off-by: Tyler Davis --- plugins/auth-backend/api-report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 649a31c963..687852f786 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -204,6 +204,7 @@ export type CloudflareAccessResult = { claims: CloudflareAccessClaims; cfIdentity: CloudflareAccessIdentityProfile; expiresInSeconds?: number; + jwt: string; }; // @public From 1b66ad8c3b975966fe5ee54df146e1b727ae4c20 Mon Sep 17 00:00:00 2001 From: Tyler Davis Date: Mon, 22 Aug 2022 08:38:04 +1000 Subject: [PATCH 3/6] review comments Signed-off-by: Tyler Davis --- plugins/auth-backend/api-report.md | 2 +- .../src/providers/cloudflare-access/provider.ts | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 687852f786..d4472504a9 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -204,7 +204,7 @@ export type CloudflareAccessResult = { claims: CloudflareAccessClaims; cfIdentity: CloudflareAccessIdentityProfile; expiresInSeconds?: number; - jwt: string; + token: string; }; // @public diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts index 38205c9cff..c2cf8b6158 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts @@ -153,7 +153,7 @@ export type CloudflareAccessResult = { claims: CloudflareAccessClaims; cfIdentity: CloudflareAccessIdentityProfile; expiresInSeconds?: number; - jwt: string; + token: string; }; /** @@ -263,7 +263,11 @@ export class CloudflareAccessAuthProvider implements AuthProviderRouteHandlers { const sub = verifyResult.payload.sub; const cfAccessResultStr = await this.cache?.get(`${CACHE_PREFIX}/${sub}`); if (typeof cfAccessResultStr === 'string') { - return JSON.parse(cfAccessResultStr) as CloudflareAccessResult; + const result = JSON.parse(cfAccessResultStr) as CloudflareAccessResult; + return { + ...result, + token: jwt, + } } const claims = verifyResult.payload as CloudflareAccessClaims; // Builds a passport profile from JWT claims first @@ -274,14 +278,16 @@ export class CloudflareAccessAuthProvider implements AuthProviderRouteHandlers { const cfIdentity = await this.getIdentityProfile(jwt); // Stores a stringified JSON object in cfaccess provider cache only when // we complete all steps - const cfAccessResult: CloudflareAccessResult = { + const cfAccessResult = { claims, cfIdentity, expiresInSeconds: claims.exp - claims.iat, - jwt, }; this.cache?.set(`${CACHE_PREFIX}/${sub}`, JSON.stringify(cfAccessResult)); - return cfAccessResult; + return { + ...cfAccessResult, + token: jwt, + }; } catch (err) { throw new ForwardedError( 'Failed to populate access identity information', From 477d05d9c749c4e824ffa08f8be3b3572dfab94b Mon Sep 17 00:00:00 2001 From: Tyler Davis Date: Mon, 22 Aug 2022 09:08:46 +1000 Subject: [PATCH 4/6] prettier Signed-off-by: Tyler Davis --- .../auth-backend/src/providers/cloudflare-access/provider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts index c2cf8b6158..f7cb7c7283 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.ts @@ -267,7 +267,7 @@ export class CloudflareAccessAuthProvider implements AuthProviderRouteHandlers { return { ...result, token: jwt, - } + }; } const claims = verifyResult.payload as CloudflareAccessClaims; // Builds a passport profile from JWT claims first From 5296f719f52af23cc7fe4dad68ba480b2505c673 Mon Sep 17 00:00:00 2001 From: Tyler Davis Date: Tue, 23 Aug 2022 10:49:38 +1000 Subject: [PATCH 5/6] add verification to test authHandler and signInResolver Signed-off-by: Tyler Davis --- .../cloudflare-access/provider.test.ts | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts index 21ec7371e5..950e9d5ef0 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts @@ -138,12 +138,24 @@ describe('CloudflareAccessAuthProvider', () => { const provider = new CloudflareAccessAuthProvider({ teamName: 'foobar', resolverContext: {} as AuthResolverContext, - authHandler: async ({ claims }) => ({ - profile: { - email: claims.email, - }, - }), - signInResolver: async () => { + authHandler: async (result) => { + expect(result).toEqual(expect.objectContaining({ + claims: mockClaims, + cfIdentity: mockCfIdentity, + token: mockJwt, + })); + return { + profile: { + email: result.claims.email, + }, + }; + }, + signInResolver: async ({result}) => { + expect(result).toEqual(expect.objectContaining({ + claims: mockClaims, + cfIdentity: mockCfIdentity, + token: mockJwt, + })); return { token: 'eyblob.eyJzdWIiOiJ1c2VyOmRlZmF1bHQvamltbXltYXJrdW0iLCJlbnQiOlsidXNlcjpkZWZhdWx0L2ppbW15bWFya3VtIl19.eyblob', From fce5333d159c8245207370bc1224c4653102738a Mon Sep 17 00:00:00 2001 From: Tyler Davis Date: Tue, 23 Aug 2022 10:50:26 +1000 Subject: [PATCH 6/6] prettier Signed-off-by: Tyler Davis --- .../cloudflare-access/provider.test.ts | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts index 950e9d5ef0..7570eb9156 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts @@ -138,24 +138,28 @@ describe('CloudflareAccessAuthProvider', () => { const provider = new CloudflareAccessAuthProvider({ teamName: 'foobar', resolverContext: {} as AuthResolverContext, - authHandler: async (result) => { - expect(result).toEqual(expect.objectContaining({ - claims: mockClaims, - cfIdentity: mockCfIdentity, - token: mockJwt, - })); + authHandler: async result => { + expect(result).toEqual( + expect.objectContaining({ + claims: mockClaims, + cfIdentity: mockCfIdentity, + token: mockJwt, + }), + ); return { profile: { email: result.claims.email, }, }; }, - signInResolver: async ({result}) => { - expect(result).toEqual(expect.objectContaining({ - claims: mockClaims, - cfIdentity: mockCfIdentity, - token: mockJwt, - })); + signInResolver: async ({ result }) => { + expect(result).toEqual( + expect.objectContaining({ + claims: mockClaims, + cfIdentity: mockCfIdentity, + token: mockJwt, + }), + ); return { token: 'eyblob.eyJzdWIiOiJ1c2VyOmRlZmF1bHQvamltbXltYXJrdW0iLCJlbnQiOlsidXNlcjpkZWZhdWx0L2ppbW15bWFya3VtIl19.eyblob',