Skip to content

feat(plugin-auth): SAML 2.0 SSO via @better-auth/sso (ADR-0069 P3)#2404

Merged
os-zhuang merged 1 commit into
mainfrom
auth/adr-0069-saml
Jun 27, 2026
Merged

feat(plugin-auth): SAML 2.0 SSO via @better-auth/sso (ADR-0069 P3)#2404
os-zhuang merged 1 commit into
mainfrom
auth/adr-0069-saml

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

What

Adds SAML 2.0 SSO as the P3 deliverable of ADR-0069.

The key finding: @better-auth/sso@1.6.20 already ships full SAML 2.0 (samlify-backed) — the same package that powers the OIDC trust list. The ADR's original "SAML is out of better-auth core" premise is stale, so no custom plugin was needed. The package exposes /sso/saml2/sp/metadata, /sso/saml2/sp/acs/:providerId, /sso/saml2/sp/slo/:providerId, and registers SAML providers through the same /sso/register endpoint with a nested samlConfig.

Changes

  • register_saml_provider action on sys_sso_provider (Setup → SSO Providers) — collects flat IdP fields (providerId, IdP EntityID, domain, IdP SSO URL, IdP signing cert PEM, NameID format).
  • runRegisterSamlProviderFromForm bridge (sibling of the OIDC one in register-sso-provider.ts) — reshapes the flat form into the nested samlConfig (entryPoint/cert/callbackUrl/spMetadata/identifierFormat), derives the per-provider ACS URL, defaults the SP descriptor, and re-dispatches through /sso/register so the admin gate runs. Returns the SP ACS + metadata URLs to configure on the IdP.
  • /api/v1/auth/admin/sso/register-saml admin route in auth-plugin.ts.
  • ADR-0069 addendum correcting the stale premise and documenting what shipped.
  • 3 unit tests for the bridge (flat→nested reshape, missing-fields 400, better-auth failure → saml_register_failed).

Verification

Suites green: plugin-auth 220, platform-objects 63. Build green.

E2E against a test IdP (mocksaml-style config):

  • POST /admin/sso/register-saml200, provider persisted in sys_sso_provider with saml_config set (oidc_config null).
  • GET /sso/saml2/sp/metadata?providerId=...200, valid SAML EntityDescriptor / SPSSODescriptor / AssertionConsumerService.
  • POST /sign-in/sso with an @example.com email → returns a valid SAMLRequest redirect to the IdP's entryPoint.

The IdP→ACS assertion round-trip (signature/replay/timestamp validation) is @better-auth/sso / samlify's tested responsibility.

🤖 Generated with Claude Code

`@better-auth/sso@1.6.20` ships full SAML 2.0 (samlify-backed), so SAML needs
no custom plugin — the same package that powers the OIDC trust list also exposes
`/sso/saml2/sp/metadata`, `/sso/saml2/sp/acs/:providerId`, and registers SAML
providers through the same `/sso/register` endpoint with a nested `samlConfig`.

- `register_saml_provider` action on `sys_sso_provider` (Setup → SSO Providers)
  collecting flat IdP fields (providerId, IdP EntityID, domain, IdP SSO URL,
  IdP signing cert, NameID format).
- `runRegisterSamlProviderFromForm` bridge (sibling of the OIDC one) reshapes the
  flat form into the nested `samlConfig`, derives the per-provider ACS URL
  (`/sso/saml2/sp/acs/<providerId>`), defaults the SP descriptor, and re-dispatches
  through `/sso/register` so the admin gate runs. Returns the SP ACS + metadata URLs.
- ADR-0069 addendum corrects the stale "SAML is out of better-auth core" premise.

Verified E2E against a test IdP: register → provider persisted with `saml_config`;
SP metadata endpoint serves a valid `EntityDescriptor`/`SPSSODescriptor`; `/sign-in/sso`
routes an email domain to the IdP with a valid `SAMLRequest` redirect.

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 6:47pm

Request Review

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

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/platform-objects, @objectstack/plugin-auth.

11 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/platform-objects, @objectstack/plugin-auth)
  • content/docs/concepts/setup-app.mdx (via @objectstack/platform-objects)
  • 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/platform-objects, @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.

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/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant