diff --git a/cloud/.env.example b/cloud/.env.example index b31adf03..b808ed80 100644 --- a/cloud/.env.example +++ b/cloud/.env.example @@ -1,7 +1,7 @@ DOMAIN_NAME=your.domain HOSTED_ZONE_ID=YOUR_AWS_HOSTED_ZONE_ID -# Enable Azure IdP -#IDP_NAME=azure +# Enable Azure IdP for SSO (using SAML) +#IDP_NAME=AZURE #AZURE_APPLICATION_ID=[your-azure-application-id] #AZURE_TENANT_ID=[your-azure-tenant-id] diff --git a/cloud/lib/auth-stack.ts b/cloud/lib/auth-stack.ts index 0537bb09..605f8a1f 100644 --- a/cloud/lib/auth-stack.ts +++ b/cloud/lib/auth-stack.ts @@ -81,7 +81,7 @@ export class AuthStack extends Stack { if (!AZURE_APPLICATION_ID) throw new Error('Missing env var AZURE_APPLICATION_SECRET'); if (!AZURE_TENANT_ID) throw new Error('Missing env var AZURE_TENANT_ID'); const idp = new UserPoolIdentityProviderSaml(this, generateResourceId('azure-idp'), { - name: 'Azure', + name: 'AZURE', userPool, metadata: UserPoolIdentityProviderSamlMetadata.url( `https://login.microsoftonline.com/${AZURE_TENANT_ID}/federationmetadata/2007-06/federationmetadata.xml?appid=${AZURE_APPLICATION_ID}` diff --git a/cloud/lib/pipeline-stack.ts b/cloud/lib/pipeline-stack.ts index 8d54fd3e..a7b8631a 100644 --- a/cloud/lib/pipeline-stack.ts +++ b/cloud/lib/pipeline-stack.ts @@ -1,8 +1,4 @@ -import { - BuildEnvironmentVariable, - BuildEnvironmentVariableType, - BuildSpec, -} from 'aws-cdk-lib/aws-codebuild'; +import { BuildEnvironmentVariableType, BuildSpec } from 'aws-cdk-lib/aws-codebuild'; import { PolicyStatement } from 'aws-cdk-lib/aws-iam'; import { IBucket } from 'aws-cdk-lib/aws-s3'; import { Stack, StackProps } from 'aws-cdk-lib/core'; @@ -41,7 +37,7 @@ export class PipelineStack extends Stack { const hostBucketName = generateResourceId('host-bucket'); - const identityProviderEnv: Record = + const identityProviderEnv = process.env.IDP_NAME?.toUpperCase() === 'AZURE' ? { IDP_NAME: { @@ -57,7 +53,7 @@ export class PipelineStack extends Stack { value: 'AZURE_TENANT_ID', }, } - : {}; + : undefined; const pipeline = new CodePipeline(this, generateResourceId('pipeline'), { synth: new ShellStep('Synth', { @@ -138,7 +134,8 @@ export class PipelineStack extends Stack { env: { CI: 'true', VITE_AUTH_PROVIDER: 'cognito', - }, + VITE_COGNITO_IDP: identityProviderEnv?.IDP_NAME.value, + } as Record, envFromCfnOutputs: { VITE_UI_DOMAIN: appStage.domainName, VITE_BACKEND_URL: appStage.backendUrl, diff --git a/frontend/.env.example b/frontend/.env.example index 32cc1fe0..03fe868d 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -1,7 +1,7 @@ VITE_BACKEND_URL=http://localhost:3000/api -# Currently only AWS Cognito is supported for remote authorization -# If you're ok with AWS, Cognito can integrate with external identity providers +# Currently only AWS Cognito is supported for remote authn/authz +# Note that Cognito can integrate with external identity providers #VITE_AUTH_PROVIDER=cognito #VITE_COGNITO_REDIRECT_URL=https://YOUR_DOMAIN #VITE_COGNITO_USERPOOL_ID=YOUR_USERPOOL_ID diff --git a/frontend/src/components/AuthProviders/CognitoAuthenticatedApp.tsx b/frontend/src/components/AuthProviders/CognitoAuthenticatedApp.tsx index bd688d7a..6ecc9764 100644 --- a/frontend/src/components/AuthProviders/CognitoAuthenticatedApp.tsx +++ b/frontend/src/components/AuthProviders/CognitoAuthenticatedApp.tsx @@ -32,6 +32,8 @@ const usernameFormField = { }, }; +const ssoProvider = import.meta.env.VITE_COGNITO_IDP; + Amplify.configure({ Auth: { Cognito: { @@ -40,7 +42,7 @@ Amplify.configure({ loginWith: { oauth: { domain: import.meta.env.VITE_COGNITO_USERPOOL_DOMAIN, - providers: [{ custom: 'Azure' }], + providers: ssoProvider ? [{ custom: ssoProvider }] : undefined, redirectSignIn: [import.meta.env.VITE_COGNITO_REDIRECT_URL], redirectSignOut: [import.meta.env.VITE_COGNITO_REDIRECT_URL], responseType: 'code', @@ -114,7 +116,7 @@ function WelcomeHeader() { return ( <> - + {ssoProvider ? : } ); } @@ -142,6 +144,7 @@ function CustomHeader({ ); } +// NOTE: Currently only Azure SSO is supported function SignInSelector() { return ( , + content: , }, ]} /> @@ -256,11 +259,11 @@ function BasicSignIn() { ); } -function SSOSignIn() { +function AzureSignIn() { function signIn() { void signInWithRedirect({ provider: { - custom: 'Azure', + custom: 'AZURE', }, }); // TODO Catch login errors, e.g. someone without SL SSO access tries their luck diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts index 6e9c6566..5eb19275 100644 --- a/frontend/src/vite-env.d.ts +++ b/frontend/src/vite-env.d.ts @@ -7,6 +7,7 @@ interface ImportMetaEnv { readonly VITE_COGNITO_USERPOOL_CLIENT: string; readonly VITE_COGNITO_USERPOOL_DOMAIN: string; readonly VITE_COGNITO_REDIRECT_URL: string; + readonly VITE_COGNITO_IDP: string; } interface ImportMeta {