feat(auth): submit auth forms through app-owned server actions - #813
Merged
Conversation
Capture the design agreed during a grilling session before implementing: auth forms will submit through app-owned server actions instead of the browser auth client. Adds the "Auth action" term to CONTEXT.md and ADR-0020 documenting the contract, the email/social redirect asymmetry, auto-added nextCookies, and the folded-in reset-password flow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XdXErtDYWN5gu8vrpcU34y
Replace the browser authClient with per-concern server-action props on the pre-built auth forms, so the auth network surface stays server-side (no /api/auth/* call from the browser) and matches the app's lib/actions/* convention. Implements ADR-0020. Package @opensaas/stack-auth: - SignInForm/SignUpForm/ForgotPasswordForm drop the authClient prop and take server-action props (signInAction, signUpAction, requestPasswordResetAction, optional signInSocialAction). Email actions return an AuthActionResult and the form redirects client-side; social sign-in redirects server-side. - New ResetPasswordForm (token via prop, confirm-password, empty-token guard) completing the previously-dead forgot-password flow. - Export the action contract types; keep [body.field] error cleanup internal. - createAuth auto-adds better-auth's nextCookies plugin (last) so the session cookie set inside a server action persists. - createClient unchanged for client-side session reading. Package @opensaas/stack-cli: - feature-generator emits lib/actions/auth.ts + a reset-password page and wires the pages to actions; no longer emits lib/auth-client.ts. Examples (starter-auth, auth-demo, mcp-demo): add lib/actions/auth.ts, wire the pages to actions, add reset-password pages, delete auth-client.ts. Docs: ADR-0020 + "Auth action" glossary term. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XdXErtDYWN5gu8vrpcU34y
Reflect the new form API in @opensaas/stack-auth's README and CLAUDE.md: forms take server-action props (not authClient), add ResetPasswordForm, document the nextCookies auto-wiring, and make the client-side session-hook section self-contained now that scaffolds no longer emit lib/auth-client.ts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XdXErtDYWN5gu8vrpcU34y
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 24dc97c The changes in this PR will be included in the next version bump. This PR includes changesets to release 9 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
Coverage Report for Core Package Coverage (./packages/core)
File CoverageNo changed files found. |
Contributor
Coverage Report for UI Package Coverage (./packages/ui)
File CoverageNo changed files found. |
Contributor
Coverage Report for CLI Package Coverage (./packages/cli)
File CoverageNo changed files found. |
Contributor
Coverage Report for Auth Package Coverage (./packages/auth)
File CoverageNo changed files found. |
Contributor
Coverage Report for Storage Package Coverage (./packages/storage)
File CoverageNo changed files found. |
Contributor
Coverage Report for RAG Package Coverage (./packages/rag)
File CoverageNo changed files found. |
Contributor
Coverage Report for Storage S3 Package Coverage (./packages/storage-s3)
File CoverageNo changed files found. |
Contributor
Coverage Report for Storage Vercel Package Coverage (./packages/storage-vercel)
File CoverageNo changed files found. |
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.
Summary
Convert the pre-built better-auth forms in
@opensaas/stack-auth/uifrom calling the browserauthClient(which hit/api/auth/*) to submitting through app-owned Next.js server actions. This keeps the auth network surface server-side (no browser dependency onNEXT_PUBLIC_APP_URL, fewer origin/CORS concerns) and matches the app's existinglib/actions/*convention. Design recorded in ADR-0020.@opensaas/stack-authSignInForm/SignUpForm/ForgotPasswordFormdrop theauthClientprop and take per-concern server-action props (signInAction,signUpAction,requestPasswordResetAction, optionalsignInSocialAction).ResetPasswordForm— token via prop (page readssearchParams.token), confirm-password mirroring sign-up, and an empty-token guard. Completes the forgot-password flow, which previously dead-ended on a missing/reset-passwordpage.AuthActionResultand the form redirects client-side (redirectTo/onSuccess/onErrorpreserved); social sign-in redirects server-side to the provider (OAuth navigates away).AuthActionResult,SignInInput,SignUpInput,RequestPasswordResetInput,ResetPasswordInput, and the action aliases); the[body.field]error cleanup stays internal to the forms.createAuthauto-adds better-auth'snextCookiesplugin as the last plugin, so the session cookie set inside a server action persists.createClientis unchanged — still available for client-side session reading (useSession).@opensaas/stack-clilib/actions/auth.ts+ areset-passwordpage and wires the auth pages to actions; it no longer emitslib/auth-client.ts.Examples
starter-auth,auth-demo,mcp-demo: addlib/actions/auth.ts, wire pages to actions, add reset-password pages, deleteauth-client.ts. (create-opensaas-app'swith-authtemplate regenerates fromstarter-auth, so it's covered automatically.)Docs
Auth actionglossary term inCONTEXT.md; packageREADME.md/CLAUDE.mdupdated to the new API.Why minor, not major
The form prop change is technically breaking, but the packages are pre-1.0 (0.x), where a minor may carry breaking changes by semver convention — released as minor per the requested versioning.
Test plan
pnpm build(all packages) green@opensaas/stack-authtests: 146 passed (incl. newcleanAuthErrorMessageunit tests)pnpm lintclean (only pre-existing warnings)tsc --noEmitclean afterpnpm generatepnpm manypkg fix+pnpm formatsearchParams-as-Promise all confirmed correct)🤖 Generated with Claude Code
https://claude.ai/code/session_01XdXErtDYWN5gu8vrpcU34y
Generated by Claude Code