Skip to content

Instantly share code, notes, and snippets.

@aldrinleal
Created May 24, 2026 18:42
Show Gist options
  • Select an option

  • Save aldrinleal/dfdb20b26dafd25787f7726528c8f867 to your computer and use it in GitHub Desktop.

Select an option

Save aldrinleal/dfdb20b26dafd25787f7726528c8f867 to your computer and use it in GitHub Desktop.
MVP-804: Cognito Custom Auth Domain — implementation plan

MVP-804: Cognito Custom Auth Domain

Goal: Replace the auto-generated Cognito hosted UI URL (us-west-2gpfpyjsfg.auth.us-west-2.amazoncognito.com) shown in iOS OAuth dialogs with branded custom domains so users see:

"SherpaHealthy" Wants to Use "auth.sherpahealthy.com" to Sign In

Domain Mapping

Env Pool ID Current domain Custom domain
Dev/Staging us-west-2_GPFPYjsFG us-west-2gpfpyjsfg.auth.us-west-2.amazoncognito.com auth.sherpahealthy-d.com
Production us-west-2_rYit4QTCG us-west-2ryit4qtcg.auth.us-west-2.amazoncognito.com auth.sherpahealthy.com

Implementation Sequence

Phase 1 — Terraform: ACM Certificates in us-east-1

Cognito custom domains require a certificate in us-east-1 regardless of the pool's home region. Both accounts already have a provider "aws" { alias = "us-east-1" } in their provider.tf.

Production — add to production/acm.tf:

resource "aws_acm_certificate" "cognito_auth" {
  provider          = aws.us-east-1
  domain_name       = "auth.sherpahealthy.com"
  validation_method = "DNS"
  lifecycle { create_before_destroy = true }
}

Sandbox — new sandbox/cognito.tf:

resource "aws_acm_certificate" "cognito_auth_d" {
  provider          = aws.us-east-1
  domain_name       = "auth.sherpahealthy-d.com"
  validation_method = "DNS"
  lifecycle { create_before_destroy = true }
}

The existing dev_cert_2 wildcard (*.sherpahealthy-d.com) lives in us-west-2 (no provider alias), so a new cert is needed.


Phase 2 — DNS: ACM Validation Records (Cloudflare, manual)

After terraform plan, add the CNAME validation records Terraform outputs to Cloudflare for both sherpahealthy.com and sherpahealthy-d.com.

  • Use DNS-only / grey cloud (no Cloudflare proxy)
  • Cert validation typically takes ~5 minutes

Phase 3 — Terraform: Cognito User Pool Domains

Run after certs are validated.

Production — add to production/cognito.tf:

resource "aws_cognito_user_pool_domain" "custom" {
  domain       = "auth.sherpahealthy.com"
  user_pool_id = module.common.cognito_user_pool_id

  custom_domain_config {
    certificate_arn = aws_acm_certificate.cognito_auth.arn
  }
}

output "cognito_custom_domain_cloudfront" {
  value = aws_cognito_user_pool_domain.custom.cloudfront_distribution
}

Also add the new IdP response URL to callback_urls in aws_cognito_user_pool_client.spa_app:

"https://auth.sherpahealthy.com/oauth2/idpresponse",

Keep the old amazoncognito.com IdP response URL until Google/Apple OAuth configs are updated (Phase 5).

Sandbox — add to sandbox/cognito.tf:

resource "aws_cognito_user_pool_domain" "custom" {
  domain       = "auth.sherpahealthy-d.com"
  user_pool_id = aws_cognito_user_pool.users.id

  custom_domain_config {
    certificate_arn = aws_acm_certificate.cognito_auth_d.arn
  }
}

output "cognito_custom_domain_cloudfront" {
  value = aws_cognito_user_pool_domain.custom.cloudfront_distribution
}

Phase 4 — DNS: Auth CNAME Records (Cloudflare, manual)

After apply, retrieve the CloudFront domain from the Terraform output and add:

Record Type Value
auth.sherpahealthy.com CNAME <output>.cloudfront.net
auth.sherpahealthy-d.com CNAME <output>.cloudfront.net

Again: DNS-only, no Cloudflare proxy.


Phase 5 — External OAuth Provider Updates (manual)

Must be done before removing old amazoncognito.com redirect URIs.

  • Google OAuth Console: add https://auth.sherpahealthy.com/oauth2/idpresponse and https://auth.sherpahealthy-d.com/oauth2/idpresponse as authorized redirect URIs in the respective OAuth clients.
  • Apple Sign-In: update the return URL in Apple's developer portal for both environments.

Phase 6 — Code Changes (app repo, separate PR)

Update domain constants once the new auth domains are confirmed live:

File Field(s)
k8s/frontend-configmap-dev.yaml COGNITO_DOMAIN
k8s/frontend-configmap-staging.yaml COGNITO_DOMAIN
k8s/frontend-configmap-production.yaml COGNITO_DOMAIN
apps/web/cognito-config.ts PROD_DOMAIN, DEV_STAGING_DOMAIN
apps/web/entrypoint.sh Default domain fallbacks
shared/lib/sherpaApiConfig.ts LEGACY_DOMAIN, PROD_COGNITO_DOMAIN
shared/view-controllers/useLoginViewController.tsx COGNITO_CONFIG.domain
apps/mobile/app/auth/login.tsx COGNITO_DOMAIN constant
apps/mobile/app/auth/screenPlay.tsx COGNITO_DOMAIN constant

After code is deployed and verified, remove the old amazoncognito.com IdP response URLs from the Cognito user pool clients and from Google/Apple consoles.


Dependency Graph

Phase 1 — TF: ACM certs (implement now, no blockers)
    ↓
Phase 2 — Cloudflare: cert validation CNAMEs  ← needs DNS access
    ↓
Phase 3 — TF: Cognito custom domains (after cert validates)
    ↓
Phase 4 — Cloudflare: auth CNAMEs             ← needs DNS access + TF output
    ↓
Phase 5 — Google/Apple OAuth console updates   ← parallel with Phase 4
    ↓
Phase 6 — App code changes                     ← deploy after Phase 4 is live

DNS access (Cloudflare) is the only external blocker. Phases 1 and 3 are pure Terraform and can be implemented immediately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment