diff --git a/CLAUDE.md b/CLAUDE.md index 1907a66..cf121f4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,6 +60,7 @@ There are no unit tests in this project. | `CUPCAKE_FRONTEND` | `localhost` | Hostname for Vite `allowedHosts` | | `NUXT_PUBLIC_OIDC_AUTHORITY` | Cognito internal pool issuer | OIDC issuer URL | | `NUXT_PUBLIC_OIDC_CLIENT_ID` | prod public Cognito client | OIDC client ID | +| `NUXT_PUBLIC_OIDC_IDENTITY_PROVIDER` | empty | Cognito IdP for sign-in (from platform `COGNITO_IDENTITY_PROVIDER`); needed for Google's account chooser | | `JWT_ENABLED` | unset | `true` in `local.env` turns login on under `pnpm dev` | Local dev needs no OIDC overrides either way; the defaults are the prod Cognito values. diff --git a/app.yaml b/app.yaml index 4fedb28..31fbce8 100644 --- a/app.yaml +++ b/app.yaml @@ -27,6 +27,7 @@ auth: COGNITO_CLIENT_ID: NUXT_PUBLIC_OIDC_CLIENT_ID COGNITO_ISSUER_URL: NUXT_PUBLIC_OIDC_AUTHORITY COGNITO_DOMAIN: NUXT_PUBLIC_OIDC_LOGOUT_DOMAIN + COGNITO_IDENTITY_PROVIDER: NUXT_PUBLIC_OIDC_IDENTITY_PROVIDER environment: CUPCAKE_BACKEND: https://cupcake-backend.javazone.no diff --git a/app/composables/useAuth.ts b/app/composables/useAuth.ts index 1120470..2d59a31 100644 --- a/app/composables/useAuth.ts +++ b/app/composables/useAuth.ts @@ -30,6 +30,7 @@ export type AuthSettings = { oidcAuthority: string oidcClientId: string oidcLogoutDomain: string + oidcIdentityProvider: string } let settings: AuthSettings | null = null @@ -52,7 +53,7 @@ let _userManager: UserManager | null = null function getUserManager(): UserManager { if (!_userManager) { - const { oidcAuthority, oidcClientId } = authSettings() + const { oidcAuthority, oidcClientId, oidcIdentityProvider } = authSettings() const origin = window.location.origin _userManager = new UserManager({ authority: oidcAuthority, @@ -63,6 +64,16 @@ function getUserManager(): UserManager { userStore: new WebStorageStateStore({ store: window.sessionStorage }), automaticSilentRenew: false, loadUserInfo: false, + // Ask Google for its account chooser, so a browser signed in to a + // personal Google account can switch to the @java.no one instead of + // being refused (the platform's COGNITO_EXTRA_AUTH_PARAMS). Managed + // login forwards prompt only when identity_provider names the IdP. + extraQueryParams: { + prompt: "select_account", + ...(oidcIdentityProvider + ? { identity_provider: oidcIdentityProvider } + : {}), + }, }) } return _userManager diff --git a/app/plugins/auth.client.ts b/app/plugins/auth.client.ts index 09b363b..75d9484 100644 --- a/app/plugins/auth.client.ts +++ b/app/plugins/auth.client.ts @@ -17,6 +17,7 @@ export default defineNuxtPlugin(async () => { oidcAuthority: config.oidcAuthority, oidcClientId: config.oidcClientId, oidcLogoutDomain: config.oidcLogoutDomain, + oidcIdentityProvider: config.oidcIdentityProvider, }) if (!config.authEnabled) return diff --git a/nuxt.config.ts b/nuxt.config.ts index bd255fc..def0c07 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -26,6 +26,10 @@ export default defineNuxtConfig({ // http://localhost:3000/ so local login works against the same pool oidcClientId: "70picsu9i2ubl8vpu4p587isqa", oidcLogoutDomain: "javabin-internal.auth.eu-central-1.amazoncognito.com", + // Cognito IdP to sign in through (platform COGNITO_IDENTITY_PROVIDER). + // Empty locally: Cognito then picks the client's only IdP, but drops + // prompt, so the Google account chooser only shows when this is set. + oidcIdentityProvider: "", }, }, diff --git a/terraform/main.tf b/terraform/main.tf index f2114a3..5f023a1 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -32,6 +32,17 @@ module "routing" { deregistration_delay = 30 } +module "network" { + source = "git::https://github.com/javaBin/platform//terraform/modules/app-network?ref=main" + + name = "cupcake" + team = "cupcake" + project = "javabin" + vpc_id = module.platform.vpc_id + port = 3000 + alb_ingress = true +} + module "auth" { source = "git::https://github.com/javaBin/platform//terraform/modules/cognito-app-client?ref=main" @@ -70,7 +81,8 @@ module "service" { execution_role_arn = module.platform.execution_role_arn task_role_arn = module.task_role.role_arn subnet_ids = module.platform.private_subnet_ids - security_group_ids = [module.platform.ecs_tasks_security_group_id] + security_group_ids = [module.network.security_group_id] + service_registry_arns = [module.network.registry_arn] region = "eu-central-1" container_user = "1000" readonly_root_filesystem = true @@ -82,13 +94,15 @@ module "service" { COGNITO_ISSUER_URL = module.auth.issuer_url COGNITO_WELL_KNOWN_URL = module.auth.well_known_url COGNITO_GROUPS = "helter" + COGNITO_EXTRA_AUTH_PARAMS = "prompt=select_account" NUXT_PUBLIC_OIDC_AUTHORITY = module.auth.issuer_url NUXT_PUBLIC_OIDC_LOGOUT_DOMAIN = module.auth.user_pool_domain } secrets = { - COGNITO_CLIENT_ID = module.auth.client_id_arn - COGNITO_IDENTITY_PROVIDER = module.auth.identity_provider_arn - NUXT_PUBLIC_OIDC_CLIENT_ID = module.auth.client_id_arn + COGNITO_CLIENT_ID = module.auth.client_id_arn + COGNITO_IDENTITY_PROVIDER = module.auth.identity_provider_arn + NUXT_PUBLIC_OIDC_CLIENT_ID = module.auth.client_id_arn + NUXT_PUBLIC_OIDC_IDENTITY_PROVIDER = module.auth.identity_provider_arn } }