Repository navigation
fix(auth)!: give no session until a required email is verified - #143
Merged
Merged
Conversation
Sign-up minted a session for every new account, so with auth.require_email_verification on you could sign up, open another tab and use the app before entering the code. The UI showed "verify your email" while the cookie already worked. Sign-up now creates the account and sends the code, and hands out no session or cookie while the email has to be verified. IssueSession refuses an unverified email too, so passkeys, magic links and social sign-in follow the same rule. Accounts with no email aren't affected. The rule itself lives in one place, EmailVerificationRequired. Sign-in and the client config used to resolve it differently, so the UI could ask for a code the server didn't need, or the other way round. The duplicate-email decoy now matches a pending sign-up exactly. BREAKING CHANGE: while verification is required, /v1/signup and Engine.SignUp return the user with no session (empty tokens over HTTP, a nil session in Go). Sign the user in from /v1/verify-email, which returns a session once the code is right, or turn the setting off.
Herald v1.10.0 brings the file driver, so an app on Authsome can write mail to a folder in development. It needs forge v1.13.2, grove v1.10.1, chronicle v1.9.1 and go-utils v1.5.0, which come along with it; those are the versions Loomplane already runs.
CI's pnpm audit --audit-level=high has failed on main since 1a2d53f. This clears it: Storybook 8.6.19, Next 16.4.1 in the Next.js package, Vite 6.4.4 under Storybook, undici 7.30.1 and zod 4.6.6. All are patch or minor releases on the same major. Vitest's Vite was the stubborn one. pnpm installs it as an automatic peer and kept the 8.2.2 in the lockfile, which no override reached, so the four packages that run Vitest now declare vite ^8.2.4 themselves. It's their peer anyway. Six moderate advisories remain, under the audit's threshold.
govulncheck flags GO-2026-6809 in crypto/x509 on go1.26.9: the SMTP mailer reaches certificate verification through tls.Dialer. Go 1.26.10 fixes it. CI's setup-go reads the version from go.mod, so this is the whole change.
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.
With
auth.require_email_verificationon, you could sign up, open the app in another tab and use it without ever entering the code. Sign-up minted a session for every new account and set the cookie, and only password sign-in checked verification. So the UI said "verify your email" while the cookie already worked.What changes
While verification is required,
Engine.SignUpcreates the account, sends the code and returns no session. Over HTTP,/v1/signupanswers 201 with the user, empty tokens and no cookie./v1/verify-emailalready signs the user in once the code is right, so that's the way in.IssueSessionrefuses an unverified email too. Every sign-in method mints its session there, so passkeys, magic links and social sign-in follow the same rule as passwords. Accounts with no email (phone, anonymous) aren't affected, and the verify-email paths mark the user verified before they sign anyone in.The rule lives in one place now,
EmailVerificationRequired. Sign-in worked it out from the dynamic setting, then the app's override, then the environment, while the client config the UI reads only looked at the environment'sSkipEmailVerification. That meant the UI could ask for a code the server didn't need (which is how this showed up in Loomplane) or skip one it did. Sign-in, sign-up,IssueSessionand the client config all ask the same function.Two smaller fixes ride along. The duplicate-email decoy returns the same pending shape as a real sign-up when verification is on, which its own comment had been waiting for. And the subscription plugin read the app ID off the session in
OnAfterSignUpand bailed out without one; it reads it off the user now.Herald
This also moves Authsome to Herald v1.10.0, which has the new file driver, so you can write mail to a folder in development. Herald needs forge v1.13.2, grove v1.10.1, chronicle v1.9.1 and go-utils v1.5.0, so those come along. Loomplane already runs that exact set, and the whole suite passes on it.
UI dependencies
CI's
pnpm audit --audit-level=highhas failed onmainsince 1a2d53f, so it failed here too. The third commit clears it: Storybook 8.6.19, Next 16.4.1, Vite 6.4.4 under Storybook, undici 7.30.1 and zod 4.6.6, all on the same major. The four packages that run Vitest now declarevite ^8.2.4themselves, because pnpm kept auto-installing Vitest's peer at 8.2.2 and no override reached it. Build, typecheck, lint and tests pass locally, and six moderate advisories are left under the threshold.Breaking
While verification is required,
/v1/signupreturns empty tokens andEngine.SignUpreturns a nil session. If you relied on getting a session straight from sign-up, sign the user in from/v1/verify-emailinstead, or turn the setting off. The UI packages already cope:signUp()moves toverification_pendingwhen verification is required.Setup
The console's first-run setup writes no cookie until the owner verifies. That matches the rule from e0286f4: whoever reaches a fresh deployment first can't take it with an address they don't control. If your app already proves the operator some other way, a setup token for example, you can verify the owner yourself with
AdminUpdateUserand then callIssueSession. That's what Loomplane does.Checked
IssueSessiongate and accounts with no email, one rule for enforcement and the client config, and the HTTP contract (no token, no cookie, a matching decoy).testutil.CreateUserissues a session after verifying, and the SDK cookie tests sign in a verified user.go test ./...passes, andgolangci-lintis clean on the changed packages./me.