You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@better-auth/sso's discovery validation requires every IdP endpoint origin to
be in trustedOrigins — even for a publicly-routable IdP — so registering any
external IdP returned 400 discovery_untrusted_origin unless pre-listed in boot
config, breaking ADR-0024's runtime self-service promise.
When the SSO RP is enabled, expose trustedOrigins as a per-request function
that, for POST /sso/register|/sso/update-provider, additionally trusts the
PUBLIC-ROUTABLE issuer/oidcConfig endpoint origins from the request body
(@better-auth/core isPublicRoutableHost). Private/internal/loopback hosts are
never auto-trusted; better-auth's DNS-resolution checks still apply.
Verified E2E: a same-origin public IdP (GitLab.com) now registers at runtime
with no boot config (was 400); the admin gate still fires before discovery.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`@better-auth/sso`'s discovery validation requires every IdP endpoint origin to be in `trustedOrigins` — even for a publicly-routable IdP. That broke ADR-0024's "register your OIDC IdP at runtime, no boot config" promise: registering any external IdP returned `400 discovery_untrusted_origin` unless the operator had pre-listed it.
8
+
9
+
When the external-SSO RP is enabled, `trustedOrigins` is now exposed as a per-request function that, for a `POST /sso/register` | `/sso/update-provider`, additionally trusts the **public-routable** issuer / `oidcConfig` endpoint origins declared in the request body (via `@better-auth/core`'s own `isPublicRoutableHost`). Private / internal / loopback hosts are never auto-trusted — they still require explicit `trustedOrigins` config (the documented SSRF escape hatch), and better-auth's own DNS-resolution checks still apply.
10
+
11
+
Verified: a same-origin public IdP (GitLab.com — issuer and all discovered endpoints on one origin, like Okta / Entra / Auth0 / Keycloak) now registers at runtime with no boot config (was a hard 400). The admin gate still fires first (a non-admin is rejected before discovery runs). Note: IdPs that split endpoints across multiple domains (e.g. Google's `accounts.google.com` + `oauth2.googleapis.com`) still need those extra origins in `trustedOrigins`.
0 commit comments