Skip to content

fix(auth): trust public-routable external-IdP origins at SSO registration (ADR-0024 / cloud#551)#2370

Merged
os-zhuang merged 1 commit into
mainfrom
adr-0024-sso-public-idp-trust
Jun 27, 2026
Merged

fix(auth): trust public-routable external-IdP origins at SSO registration (ADR-0024 / cloud#551)#2370
os-zhuang merged 1 commit into
mainfrom
adr-0024-sso-public-idp-trust

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Why

Follow-up to #2363 (the cloud#551 SSO admin-gate). Local E2E surfaced a second gap: @better-auth/sso's discovery validation (validateDiscoveryUrl + normalizeAndValidateUrl) requires every IdP endpoint origin to be in trustedOrigins — even for a publicly-routable IdP. So registering any external OIDC IdP returns 400 discovery_untrusted_origin unless the operator pre-listed it, which breaks ADR-0024's "register your IdP at runtime, no boot config" promise.

What

When the external-SSO RP is enabled (isSsoWired()), trustedOrigins is now 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 — using @better-auth/core's own isPublicRoutableHost (the same predicate better-auth's sub-endpoint check uses). All other requests get exactly the previous static origins.

Safety:

  • Private / internal / loopback hosts are never auto-trusted — they still require explicit trustedOrigins config (the documented SSRF escape hatch).
  • better-auth's own DNS-resolution checks still apply.
  • The function is only consulted for the two SSO admin paths; normal CSRF/origin behavior is unchanged.

Verification (browser E2E, local prod-like stack, no trustedOrigins entry)

  • Same-origin public IdP GitLab.com (issuer + all discovered endpoints on one origin — like Okta / Entra / Auth0 / Keycloak) → register 200, oidcConfig hydrated from GitLab's live discovery (was a hard 400).
  • Google's main discovery URL now passes too; Google still needs its split googleapis.com endpoint origins trusted (documented caveat — multi-domain IdPs).
  • Regression: a non-admin registering a valid public IdP is still 403 (the fix(auth): admin-gate self-service SSO provider registration + default-role JIT (ADR-0024 / cloud#551) #2363 admin gate fires before discovery); normal auth flows intact.

Scope

Only packages/plugins/plugin-auth/src/auth-manager.ts (+ changeset). SSO mechanism stays framework-open.

🤖 Generated with Claude Code

…tion (ADR-0024 / cloud#551)

@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>
@vercel

vercel Bot commented Jun 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 27, 2026 1:43pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tooling size/s labels Jun 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/plugin-auth.

10 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/implementation-status.mdx (via @objectstack/plugin-auth)
  • content/docs/concepts/packages.mdx (via @objectstack/plugin-auth)
  • content/docs/getting-started/cli.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/auth-sso.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/authentication.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/kernel-services.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/packages.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/plugins.mdx (via @objectstack/plugin-auth)
  • content/docs/guides/production-readiness.mdx (via @objectstack/plugin-auth)
  • content/docs/releases/v9.mdx (via @objectstack/plugin-auth)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit caa3ef4 into main Jun 27, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the adr-0024-sso-public-idp-trust branch June 27, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant