fix(auth): serve set-initial-password on per-environment runtimes (#1544)#1577
Merged
Merged
Conversation
) better-auth's `setPassword` is a server-only API (registered with no HTTP path on purpose — setting a password without proving the old one is privilege-sensitive). The full AuthPlugin wrapped it in a custom `/api/v1/auth/set-initial-password` route, but that plugin is SKIPPED on a per-environment (cloud) runtime, where auth is served by AuthProxyPlugin. There the route was absent, so the SSO-onboarded "Set local password" recovery flow POSTed it and 404'd, dead-ending first-time owner setup. - Extract the route body into a shared `runSetInitialPassword` helper that wraps `auth.api.setPassword` + normalises better-call APIErrors onto our `{ success, error }` envelope. - AuthPlugin now calls the helper (drops ~50 lines of hand-rolled getSession/hash/createAccount that had drifted from better-auth's own validation surface). - AuthProxyPlugin short-circuits `set-initial-password` before forwarding to better-auth, using the same helper so the two mount points can't drift. - Unit tests for the helper (missing arg, success header forwarding, already-set→409, length errors, 401, 500 fallback). Redirect target (profile → standalone /set-password page) is a follow-up paired with the objectui page; not flipped here to avoid a broken interim. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
) Now that objectui ships a shell-less `/set-password` auth surface (sibling of login/reset-password), point the sso-exchange "no credential yet" redirect at it instead of the full-shell profile page + `?recovery_needed=true` banner. Conventional shape for an auth screen; the profile page drops the recovery special-casing. 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
On a per-environment (cloud) runtime, the SSO-as-owner recovery flow redirects to "Set a recovery password", which POSTs
/api/v1/auth/set-initial-password→ 404, dead-ending first-time owner setup (#1544).Root cause
set-initial-passwordis a custom route registered only by the fullAuthPlugin. That plugin is skipped on a per-environment kernel (auth is served byAuthProxyPlugin), which forwards/api/v1/auth/*to better-auth — and better-auth has no such route, because itssetPasswordop is server-only by design (createAuthEndpoint({…})with no HTTP path; setting a password without proving the old one is privilege-sensitive). So the route only ever existed on the host kernel.Fix
runSetInitialPassword(authApi, request)— wraps better-auth'sauth.api.setPasswordand maps better-callAPIErrors onto the{ success, error: { code, message } }envelope the client parses. Single source of truth so the two mount points can't drift.AuthPluginnow calls the helper, dropping ~50 lines of hand-rolledgetSession/hash/createAccount/length-checks that had drifted from better-auth's own validation surface.AuthProxyPluginshort-circuitsset-initial-passwordbefore forwarding (resolves the 404), using the same helper.PASSWORD_ALREADY_SET→409, length errors, 401, 500 fallback.Not in this PR (follow-up)
The recovery UI currently lives inside the full-shell profile page (
/_console/system/profile?recovery_needed=true). Making it a standalone, shell-less page like login (/set-password) is an objectui change; the one-line redirect-target flip here is paired with it to avoid a broken interim state.Verification
tsc --noEmitclean: plugin-auth + runtime🤖 Generated with Claude Code