#14799·amplify-js

Make OAuth Hosted UI URL scheme configurable for local Cognito emulators

Author: prandogabrielCreated Apr 30, 2026Updated Jul 8, 2026
Labelsfeature-requestAuth

Describe the feature you'd like to request

Make the OAuth Hosted UI URL scheme configurable so that local Cognito emulators (LocalStack, MiniStack, custom dev proxies) can be reached over http:// without requiring a TLS-terminating proxy in front of them.

Three OAuth flow URL builders currently hardcode https:// against the Cognito Hosted UI domain:

File Line Code
packages/auth/src/providers/cognito/apis/signInWithRedirect.ts 148 `https://${domain}/oauth2/authorize?${params.toString()}`
packages/auth/src/providers/cognito/utils/oauth/completeOAuthFlow.ts 96 'https://' + domain + '/oauth2/token'
packages/auth/src/providers/cognito/utils/oauth/oAuthSignOutRedirect.ts 21 `https://${domain}/logout?...`

Real Cognito Hosted UI is always HTTPS, so the hardcode is correct for production AWS — but it makes Amplify essentially impossible to use against a Cognito emulator unless the user stands up a separate Caddy/nginx/Traefik in front of the emulator just to terminate TLS.

Describe the solution you'd like

Three possible shapes, ranked from most backward-compatible to most explicit:

Option A — accept a full URL in domain (smallest diff, no new config field)

If Cognito.loginWith.oauth.domain starts with http:// or https://, use it verbatim and skip the prepended https://. Otherwise, fall back to today's behavior (https://${domain}).

typescript
const baseUrl = /^https?:\/\//.test(domain) ? domain : `https://${domain}`;
const oAuthUrl = `${baseUrl}/oauth2/authorize?${params.toString()}`;
typescript
// User config:
loginWith: {
  oauth: {
    domain: 'http://localhost:4566',      // local emulator → http
    // domain: 'auth.myapp.com',          // production → still https
  },
},

This is the minimal change and mirrors how userPoolEndpoint already accepts a full URL for SDK calls.

Option B — separate protocol field on the OAuth config

typescript
loginWith: {
  oauth: {
    domain: 'localhost:4566',
    protocol: 'http',                     // defaults to 'https'
  },
},

More explicit, but introduces a new config surface to document.

Option C — environment- or build-flag-gated

Only honor an HTTP override when an explicit dev flag is set (e.g. process.env.AMPLIFY_OAUTH_INSECURE_LOCAL). Defends against accidental misconfiguration shipping to production but adds complexity.

I'd lean toward Option A — single conditional, no new config, no new flag, and the URL parsing makes the intent obvious in user config.

Describe alternatives you've considered

  • Run a TLS-terminating reverse proxy in front of the Cognito emulator. Works but doubles the local-dev infra and complicates the cert-trust story (every dev has to run mkcert -install or click through browser warnings). This is what we've been doing as the workaround. The same workaround was suggested by maintainers in #14463 (same flavor of issue: hardcoded AWS URLs in the JWT verifier blocking LocalStack).
  • Self-signed certs on the emulator (e.g., the MiniStack USE_SSL=1 flag I shipped recently). Solves the protocol mismatch but every browser / SDK consumer has to accept self-signed certs. Solves "TLS exists" but not "trust" — mkcert is still the norm. A simple domain: 'http://...' would skip that whole class of friction for read-only dev work.

Additional context

The closed issue #14463 shows there's existing demand for the broader pattern (Amplify + local Cognito emulators). It was closed with "use a proxy as a workaround" — but the fact that it keeps coming up suggests the workaround isn't free. Cognito emulation is an established part of the local-dev ecosystem (LocalStack has shipped it for years; MiniStack and several smaller emulators support it too) and the OAuth Hosted UI flow is one of the few remaining Amplify code paths that can't run against a local emulator without significant scaffolding.

Happy to send a PR for Option A if it sounds right.