User Authentication Flow
Registration and login behavior for every authentication provider, and how the system handles cross-provider conflicts and password resets for OAuth2 and Email-Password auth.
Overview
The system supports five sign-in methods and enforces one of two trust models per provider when an email collides across providers:
Cannot be linked with any other authentication method. A conflicting email blocks registration/login outright.
Can be connected via a shared, verified email. Registering or logging in with one auto-links the others.
Authentication flow diagram
Rendered client-side via Mermaid. If this loads offline, the diagram won't appear โ see the source Markdown for the raw definition.
Providers
๐ Facebook Strict isolation
- No email verification required
- Prevents duplicate Facebook accounts
- Blocks if email exists on Email or Google
- One authentication method per email, enforced
- Only succeeds if the user originally registered via Facebook
๐ Google Flexible linking
- Prevents duplicate Google accounts
- Blocks if email exists on Facebook or X
- Connects to an existing Email or Apple account automatically
- Works for Google OAuth, email-based, and Apple-linked accounts
- Blocks Facebook/X conflicts
- Auto-links an existing Email or Apple account
โ X (Twitter) Strict isolation
- No email verification required
- Prevents duplicate X accounts
- Blocks if email exists on Email, Google, or Facebook
- One authentication method per email, enforced
- Only succeeds if the user originally registered via X
- Cannot be linked with any other method
Apple Flexible linking
- Deduplicated by Apple's
subprovider ID - Blocks if email exists on Facebook or X
- Connects to an existing Email or Google account (Apple's email claim is itself Apple-verified)
- Works for Apple Sign In, email-based, and Google-linked accounts
- Blocks Facebook/X conflicts
- Auto-links an existing Email or Google account
๐ง Email/Password Flexible linking
- Blocked if email exists on Facebook or X
- Auto-connects an existing Google or Apple account
- Facebook/X-only accounts never receive a reset email (silent no-op)
- Email, Google, and Apple accounts can reset
Error codes and messages
| Error code | Error key | Description |
|---|---|---|
USER_ALREADY_EXISTS | user.alreadyExists | Provider account already exists |
PROFILE_LINKED_TO_NON_FACEBOOK | profile.linkedToNonFacebook | Email is associated with Email/Google/X/Apple account |
PROFILE_LINKED_TO_FACEBOOK | profile.linkedToFacebook | Email is associated with Facebook account |
PROFILE_LINKED_TO_NON_X | profile.linkedToNonX | Email is associated with Email/Google/Facebook/Apple account |
PROFILE_LINKED_TO_X | profile.linkedToX | Email is associated with X account |
APPLE_MISSING_EMAIL | apple.missingEmail | Apple identity token did not include an email claim |
USER_NOT_FOUND | user.notFound | User does not exist in the system |
USER_INCORRECT_EMAIL_PASS | user.incorrectEmailOrPassword | User gave incorrect email or password |
Security considerations
OAuth-only accounts (Facebook, X) don't receive password reset emails โ this prevents information disclosure about which accounts exist.
Every OAuth provider ID is checked for uniqueness to prevent duplicate account creation.
Facebook and X registrations skip email verification but enforce strict isolation instead, blocking any cross-provider linking or takeover attempt.
Facebook & X โ strict isolation, cannot link with any other method. Google, Apple & Email โ flexible linking via shared verified email. This hybrid balances social-account isolation against identity-provider convenience.
X and Facebook use strict isolation because a temporary account compromise could otherwise link to existing accounts. Google, Apple, and Email linking is safer since all three require verified email โ Apple's claim comes from a signed identity token verified against Apple's published keys.