feat(auth): surface features.sso in public /auth/config#2330
Merged
Conversation
getPublicConfig() advertised every other auth capability flag (oidcProvider, twoFactor, multiOrgEnabled, …) but omitted enterprise SSO, even though the manager already computes whether @better-auth/sso is wired (OS_SSO_ENABLED / plugins.sso). The login UI therefore had nothing to gate on and rendered the "Sign in with SSO" button unconditionally; on a deployment without SSO wired, clicking it only then surfaced "No SSO provider is configured for this email domain." features.sso is now resolved with the EXACT logic that decides whether the plugin is mounted in buildPlugins(), so the advertised capability can never disagree with the actual /sign-in/sso route. Tests cover default-off, config-on, and OS_SSO_ENABLED env override. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 10 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
Follow-up to the coarse features.sso flag: getPublicConfig() still returns the "wired" capability (cheap, sync), but the /auth/config route now refines it to "usable" via the new AuthManager.isSsoUsable() — wired AND >=1 sys_sso_provider row exists. This hides the "Sign in with SSO" button not only when SSO is off but also when it's enabled yet no IdP is configured yet (previously the button showed and errored for everyone at click time). isSsoUsable() only queries sys_sso_provider when wired and fails OPEN to the wired flag on any introspection failure (no data engine, query throws), so the login config endpoint never 500s. The coarse computation is factored into a private isSsoWired() shared by getPublicConfig() and isSsoUsable(). Both the plugin-auth route and the hono adapter /config path apply the refinement (the latter guarded so it's a no-op against an older auth service). 5 new unit tests cover not-wired, zero-providers, >=1 provider, no-engine fail-open, and query-throws fail-open. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 6, 2026
* chore: bump objectui to c27bd3264f39 feat(studio): per-object API / Hooks / Actions tabs + Data-pillar polish (#2330) objectui@c27bd3264f394bec5f5f71326118bfb115fbe884 * chore(cli): stop default-loading @objectstack/studio app package os dev / os start / os serve no longer register the Studio one-app package by default. The console ships a dedicated Studio surface at /_console/studio/<pkg>/<pillar>, so Studio no longer needs to exist as a navigable app tile in "Your apps". Setup and Account app packages are unchanged. The @objectstack/studio package itself is kept (still registerable explicitly; ADR-0048 app-split test continues to cover it). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: add changeset for dropping default studio app load Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 6, 2026
* chore: bump objectui to c27bd3264f39 feat(studio): per-object API / Hooks / Actions tabs + Data-pillar polish (#2330) objectui@c27bd3264f394bec5f5f71326118bfb115fbe884 * docs: reframe getting-started around the AI build/verify loop Center the docs on the actual ObjectStack workflow: an AI agent (Claude Code) authors typed metadata, a validation gate catches silent-at-runtime mistakes, the human verifies in the visual Console, and the built app is itself AI-operable over MCP. - New flagship tutorial "Build with Claude Code" — the whole loop on a live-built Support Desk app, grounded in real `os` CLI output. - New concept page "How AI Development Works" — why the loop is fast and safe (skills+AGENTS.md, os validate, contract-first, draft-gating, worktree). - Repurpose the old hand-authoring Quick Start into "Anatomy of an ObjectStack App" (read-to-verify); keep the /quick-start slug so inbound links survive. - Front-load the "your app is an MCP server" story: env-var value-prop, a dedicated api/index section + request-path diagram, deployment pointer. - Reframe by real development layering (Data / Automation / Interface / Access / AI) instead of the ObjectQL/ObjectOS/ObjectUI protocol trinity. - Add Mermaid diagrams (build loop, AI architecture, protocol stack, MCP request path) using the site's existing Mermaid support. - Docs-site chrome: drop the meaningless "Documentation" self-link, fix the UI Engine icon (deprecated `Layout` -> `LayoutDashboard`), hide the single-language switcher. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The console login page renders a "Sign in with SSO" button unconditionally. On a deployment where enterprise SSO isn't wired (default for self-hosted /
os dev), the/sign-in/ssoroute isn't mounted, so the button is a dead end that only reveals "No SSO provider is configured for this email domain." at click time.Root cause on the server side:
getPublicConfig()(the/auth/configpayload the SPA reads) advertised every other capability flag —oidcProvider,twoFactor,multiOrgEnabled,deviceAuthorization, … — but omitted enterprise SSO, even though the manager already computes whether@better-auth/ssois wired (OS_SSO_ENABLED/plugins.sso). The login UI had no signal to gate on.Fix
Two layers, so the advertised capability matches reality at both granularities:
Coarse (sync, cheap) —
getPublicConfig().features.ssonow reports whether the plugin is wired, resolved with the EXACT logic that decides whether it's mounted inbuildPlugins()(factored into a privateisSsoWired()). This honours the invariant the existing comment already demands: "the/auth/configresponse MUST match what's actually wired, otherwise the frontend will render UI for endpoints that 404."Precise (async, at the route) — the
/auth/confighandler refines that flag to usable via the newAuthManager.isSsoUsable(): wired AND at least onesys_sso_providerrow exists. This also hides the button when SSO is enabled but no IdP is configured yet. It only queries when wired, and fails open to the wired flag on any introspection error (no data engine, query throws) so the login config never 500s. Applied in both the plugin-auth route and the hono adapter/configpath (the latter guarded as a no-op against an older auth service).Per-email domain→IdP matching still happens at
/sign-in/sso;isSsoUsable()answers the coarser "is there any point showing the button at all".Tests
auth-manager.test.ts:features.sso(coarse): default-off, on-via-plugins.sso,OS_SSO_ENABLEDenv override.isSsoUsable()(precise): not-wired (skips query), zero-providers → false, ≥1 provider → true, no-engine fail-open, query-throws fail-open.95 plugin-auth tests green, hono suite green (67),
tsc --noEmitclean onindex.ts(3 pre-existinghono.test.tscontext-typing errors are unrelated). Browser end-to-end verification of the live/auth/config+ login page done alongside the objectui PR.Pairs with
Client-side consumer that hides the button: objectstack-ai/objectui#2006
🤖 Generated with Claude Code