You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Link a new sign-in method when the credential proves email ownership.
Derive web OAuth proof from the raw email_verified claim.
Pass verified native Apple and Google tokens through the same auto-link path.
Add settlement, callback, helper, and native route coverage.
Why
Users with the same owned email received DIFFERENT-OAUTH when they used Google and magic link in either order.
How
The shared settlement path now treats autoLinkToExistingUser=true as proof of email ownership after the existing same-provider guard. Web OAuth callers derive that value from email_verified; native Apple and Google token verification already enforces the claim.
Verification
pnpm run format:changed
pnpm run typecheck
pnpm run lint
pnpm test:db
cd apps/web && pnpm test -- src/lib/user/index.test.ts src/lib/user/server.test.ts src/lib/user/server-signin-callback.test.ts src/lib/user/sso.test.ts src/app/api/auth/native/token/route.test.ts
250 targeted tests passed.
Bot E2E passed: a Google-first account completed a browser magic-link sign-in and retained the same user id with exactly google and email providers.
E2E Notes
Real Google OAuth and provider-signed native tokens are not bot-drivable locally. Direction two and native parity use Jest coverage.
Headless Chromium could not complete the real Cloudflare Turnstile challenge. The verifier used a temporary development-only bypass in the two Turnstile files, saved patches outside the repository, and restored both files byte-for-byte before the baseline check. No bypass remains in the branch.
The E2E stack used temporary tmux environment values for the live port and host because the local env points to a stale LAN origin. The values were removed during teardown.
Reviewed the auth account-linking fix across settlement logic, web OAuth sign-in callback, and native Apple/Google token routes with high confidence: every autoLinkToExistingUser=true path is backed by genuine email-ownership proof (email_verified is enforced in verifyNativeAppleIdToken, verifyNativeGoogleIdToken, and exchangeNativeGoogleAuthCode; consumed magic-link/code tokens; dev-only fake-login), the same-provider refusal guard is retained, and providers without the claim (GitHub/GitLab/Discord) correctly keep the DIFFERENT-OAUTH refusal. Tests cover both linking directions, no-proof refusal, same-provider refusal, and the fake-login upgrade regression. No memory-leak potential introduced (pure helper + stateless request handling).
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
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
What
email_verifiedclaim.Why
Users with the same owned email received
DIFFERENT-OAUTHwhen they used Google and magic link in either order.How
The shared settlement path now treats
autoLinkToExistingUser=trueas proof of email ownership after the existing same-provider guard. Web OAuth callers derive that value fromemail_verified; native Apple and Google token verification already enforces the claim.Verification
pnpm run format:changedpnpm run typecheckpnpm run lintpnpm test:dbcd apps/web && pnpm test -- src/lib/user/index.test.ts src/lib/user/server.test.ts src/lib/user/server-signin-callback.test.ts src/lib/user/sso.test.ts src/app/api/auth/native/token/route.test.tsgoogleandemailproviders.E2E Notes
Visual Changes
N/A