From 59c5c70bf7631c959fe6550d12b7b8556fac7b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 22 Dec 2021 16:56:29 +0100 Subject: [PATCH] first minor cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/dull-peas-double.md | 2 +- docs/auth/google/gcp-iap-auth.md | 23 ++++++------ plugins/auth-backend/package.json | 4 +++ .../src/providers/gcp-iap/index.ts | 1 + .../src/providers/gcp-iap/provider.test.ts | 16 ++++----- .../src/providers/gcp-iap/provider.ts | 35 ++++++++++--------- 6 files changed, 45 insertions(+), 36 deletions(-) diff --git a/.changeset/dull-peas-double.md b/.changeset/dull-peas-double.md index 6d919c0c2c..3d1735e672 100644 --- a/.changeset/dull-peas-double.md +++ b/.changeset/dull-peas-double.md @@ -2,4 +2,4 @@ '@backstage/plugin-auth-backend': patch --- -Added Google Cloud Identity Aware Proxy as an identiy Provider - based on aws-elb +Added Google Cloud Identity-Aware Proxy as an identity provider. diff --git a/docs/auth/google/gcp-iap-auth.md b/docs/auth/google/gcp-iap-auth.md index bafc573d18..836abd4623 100644 --- a/docs/auth/google/gcp-iap-auth.md +++ b/docs/auth/google/gcp-iap-auth.md @@ -2,15 +2,15 @@ id: provider title: Google Identity Aware Proxy Provider sidebar_label: Google IAP -description: - Adding Google Identity Aware Proxy as an authentication provider in Backstage +# prettier-ignore +description: Adding Google Identity-Aware Proxy as an authentication provider in Backstage --- -# Using Google Identity Aware Proxy to authenticate requests +# Using Google Identity-Aware Proxy to authenticate requests -Backstage allows offloading the responsibility of authenticating users to an +Backstage allows offloading the responsibility of authenticating users to the Google HTTPS Load Balancer & [IAP](https://cloud.google.com/iap), leveraging the -authentication support on IAP. +authentication support on the latter. This tutorial shows how to use authentication on an ALB sitting in front of Backstage. @@ -24,10 +24,11 @@ configured to serve the frontend app from the backend. ### Frontend -The Backstage App needs a SignInPage when authentication is required. When using -IAP Proxy authentication Backstage will only be loaded once the user has -successfully authenticated; we won't need to display a SignIn page, however we -will need to create a dummy SignIn component that can refresh the token. +The Backstage App needs a `SignInPage` to be configured. When using IAP Proxy +authentication Backstage will only be loaded once the user has successfully +authenticated; we won't need to display a sign-in page as such, however we will +need to create a dummy `SignInPage` component that can decode and refresh the +token. - edit `packages/app/src/App.tsx` - import the following two additional definitions from `@backstage/core`: @@ -52,6 +53,7 @@ const refreshToken = async ({ props, discoveryApiConfig, config }) => { }); return; } + try { const request = await fetch(`${baseUrl}/gcp-iap/refresh`, { headers: { @@ -76,6 +78,7 @@ const refreshToken = async ({ props, discoveryApiConfig, config }) => { }); } }; + const DummySignInComponent: any = (props: any) => { try { const config = useApi(configApiRef); @@ -94,7 +97,7 @@ When using ALB auth it is not possible to leverage the built-in auth config discovery mechanism implemented in the app created by default; bespoke logic needs to be implemented. -- replace the content of `packages/backend/plugin/auth.ts` with the below +- Replace the content of `packages/backend/plugin/auth.ts` with the below ```ts // imports are relative - as this was tested out in repo directly diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 25f3a7fde8..bdc75f40e5 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -45,6 +45,10 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "express-session": "^1.17.1", +<<<<<<< HEAD +======= + "fs-extra": "9.1.0", +>>>>>>> 4d5fd11228 (first minor cleanups) "google-auth-library": "^7.2.0", "helmet": "^4.0.0", "jose": "^1.27.1", diff --git a/plugins/auth-backend/src/providers/gcp-iap/index.ts b/plugins/auth-backend/src/providers/gcp-iap/index.ts index 1c81aa919d..634eb37a4a 100644 --- a/plugins/auth-backend/src/providers/gcp-iap/index.ts +++ b/plugins/auth-backend/src/providers/gcp-iap/index.ts @@ -13,5 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export { createGcpIAPProvider } from './provider'; export type { GcpIAPProviderOptions } from './provider'; diff --git a/plugins/auth-backend/src/providers/gcp-iap/provider.test.ts b/plugins/auth-backend/src/providers/gcp-iap/provider.test.ts index 43a6d25dac..d2a70c043c 100644 --- a/plugins/auth-backend/src/providers/gcp-iap/provider.test.ts +++ b/plugins/auth-backend/src/providers/gcp-iap/provider.test.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { getVoidLogger } from '@backstage/backend-common'; import express from 'express'; - -import { GcpIAPProvider } from './provider'; import { AuthResponse } from '../types'; +import { GcpIAPProvider } from './provider'; jest.mock('google-auth-library'); @@ -57,22 +57,22 @@ describe('GcpIAPProvider', () => { getEntityByName: jest.fn(), }; - const mockRequest = ({ + const mockRequest = { header: jest.fn(() => { return 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZvbyIsImlzcyI6ImZvbyJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.T2BNS4G-6RoiFnXc8Q8TiwdWzTpNitY8jcsGM3N3-Yo'; }), - } as unknown) as express.Request; - const mockRequestWithoutJwt = ({ + } as unknown as express.Request; + const mockRequestWithoutJwt = { header: jest.fn(() => { return undefined; }), - } as unknown) as express.Request; - const mockResponse = ({ + } as unknown as express.Request; + const mockResponse = { end: jest.fn(), header: () => jest.fn(), json: jest.fn().mockReturnThis(), status: jest.fn(), - } as unknown) as express.Response; + } as unknown as express.Response; describe('should transform to type OAuthResponse', () => { it('when JWT is valid and identity is resolved successfully', async () => { diff --git a/plugins/auth-backend/src/providers/gcp-iap/provider.ts b/plugins/auth-backend/src/providers/gcp-iap/provider.ts index c437dadda0..33235083ca 100644 --- a/plugins/auth-backend/src/providers/gcp-iap/provider.ts +++ b/plugins/auth-backend/src/providers/gcp-iap/provider.ts @@ -14,19 +14,17 @@ * limitations under the License. */ +import { CatalogApi } from '@backstage/catalog-client'; +import express from 'express'; +import { OAuth2Client } from 'google-auth-library'; +import { Logger } from 'winston'; import { - AuthProviderRouteHandlers, + AuthProviderFactory, AuthProviderFactoryOptions, + AuthProviderRouteHandlers, ExperimentalIdentityResolver, } from '../types'; -import express from 'express'; - -import { Logger } from 'winston'; -import { CatalogApi } from '@backstage/catalog-client'; - -import { OAuth2Client } from 'google-auth-library'; - const IAP_JWT_HEADER = 'x-goog-iap-jwt-assertion'; export type GcpIAPProviderOptions = { @@ -47,6 +45,7 @@ export class GcpIAPProvider implements AuthProviderRouteHandlers { this.catalogClient = catalogClient; this.options = options; } + frameHandler(): Promise { return Promise.resolve(undefined); } @@ -102,7 +101,9 @@ export class GcpIAPProvider implements AuthProviderRouteHandlers { } } -export const createGcpIAPProvider = (_options?: GcpIAPProviderOptions) => { +export function createGcpIapProvider( + _options?: GcpIAPProviderOptions, +): AuthProviderFactory { return ({ logger, catalogApi, @@ -111,13 +112,13 @@ export const createGcpIAPProvider = (_options?: GcpIAPProviderOptions) => { }: AuthProviderFactoryOptions) => { const audience = config.getString('audience'); if (identityResolver !== undefined) { - return new GcpIAPProvider(logger, catalogApi, { - audience, - identityResolutionCallback: identityResolver, - }); + throw new Error( + 'Identity resolver is required to use this authentication provider', + ); } - throw new Error( - 'Identity resolver is required to use this authentication provider', - ); + return new GcpIAPProvider(logger, catalogApi, { + audience, + identityResolutionCallback: identityResolver, + }); }; -}; +}