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.

๐Ÿ“ง Email/Password ๐Ÿ…– Google OAuth ๐Ÿ“˜ Facebook OAuth โœ• X (Twitter) OAuth Apple Sign In

Overview

The system supports five sign-in methods and enforces one of two trust models per provider when an email collides across providers:

๐Ÿ”’
Strict isolation โ€” Facebook & X

Cannot be linked with any other authentication method. A conflicting email blocks registration/login outright.

๐Ÿ”—
Flexible linking โ€” Google, Apple & Email

Can be connected via a shared, verified email. Registering or logging in with one auto-links the others.

Authentication flow diagram

100% Drag to pan ยท scroll/pinch to zoom
flowchart TD
    A["User Attempts
    Authentication"] --> B{"Authentication
    Method"}

    B -->|"Facebook
    Sign-up"| C["Facebook
    Registration Flow"]
    B -->|"Facebook
    Sign-in"| D["Facebook
    Login Flow"]
    B -->|"Email
    Registration"| E["Email
    Registration Flow"]
    B -->|"Google
    Registration"| F["Google
    Registration Flow"]
    B -->|"Google
    Sign-in"| H["Google
    Login Flow"]
    B -->|"X
    Registration"| I["X
    Registration Flow"]
    B -->|"X
    Sign-in"| J["X
    Login Flow"]
    B -->|"Apple
    Registration"| K["Apple
    Registration Flow"]
    B -->|"Apple
    Sign-in"| L["Apple
    Login Flow"]
    B -->|"Password
    Reset"| G["Password
    Reset Flow"]

    C --> C1{"Facebook provider ID
    already exists?"}
    C1 -->|"Yes"| C5["USER_ALREADY_EXISTS
    User already exists"]
    C1 -->|"No"| C2{"Email exists
    in DB?"}
    C2 -->|"No"| C3["Allow signup
    โœ… Success"]
    C2 -->|"Yes - Email"| C4["PROFILE_LINKED_TO_NON_FACEBOOK"]
    C2 -->|"Yes - Google"| C6["PROFILE_LINKED_TO_NON_FACEBOOK"]

    D --> D1{"Email linked to
    non-FB account?"}
    D1 -->|"Yes - Email"| D4["PROFILE_LINKED_TO_NON_FACEBOOK"]
    D1 -->|"Yes - Google"| D5["PROFILE_LINKED_TO_NON_FACEBOOK"]
    D1 -->|"No"| D2{"Facebook profile
    exists?"}
    D2 -->|"No"| D3["USER_NOT_FOUND"]
    D2 -->|"Yes"| D6["โœ… Login successful"]

    E --> E1{"Email linked
    to Facebook?"}
    E1 -->|"No"| E2["โœ… Allow registration"]
    E1 -->|"Yes"| E3["PROFILE_LINKED_TO_FACEBOOK"]

    F --> F1{"Google provider ID
    already exists?"}
    F1 -->|"Yes"| F4["USER_ALREADY_EXISTS"]
    F1 -->|"No"| F2{"Email linked
    to Facebook?"}
    F2 -->|"No"| F3["โœ… Allow Google registration"]
    F2 -->|"Yes"| F5["PROFILE_LINKED_TO_FACEBOOK"]

    H --> H1{"Email linked to
    Facebook?"}
    H1 -->|"Yes"| H4["PROFILE_LINKED_TO_FACEBOOK"]
    H1 -->|"No"| H2{"Google profile OR
    email profile exists?"}
    H2 -->|"No"| H3["USER_NOT_FOUND"]
    H2 -->|"Yes"| H5["โœ… Login successful"]

    G --> G1{"Check user
    profile type"}
    G1 -->|"Facebook/X-only"| G2["โŒ No reset
    Silent fail"]
    G1 -->|"Email/Google/Apple"| G3["โœ… Send
    reset email"]

    I --> I1{"X provider ID
    already exists?"}
    I1 -->|"Yes"| I5["USER_ALREADY_EXISTS"]
    I1 -->|"No"| I2{"Email exists
    in DB?"}
    I2 -->|"No"| I3["Allow signup
    โœ… Success"]
    I2 -->|"Yes - Email"| I4["PROFILE_LINKED_TO_NON_X"]
    I2 -->|"Yes - Google/FB"| I6["PROFILE_LINKED_TO_NON_X"]

    J --> J1{"Email linked to
    non-X account?"}
    J1 -->|"Yes"| J4["PROFILE_LINKED_TO_NON_X"]
    J1 -->|"No"| J2{"X profile
    exists?"}
    J2 -->|"No"| J3["USER_NOT_FOUND"]
    J2 -->|"Yes"| J6["โœ… Login successful"]

    K --> K1{"Apple provider ID
    already exists?"}
    K1 -->|"Yes"| K4["USER_ALREADY_EXISTS"]
    K1 -->|"No"| K2{"Email linked
    to Facebook or X?"}
    K2 -->|"Yes"| K6["PROFILE_LINKED_TO_FACEBOOK / X"]
    K2 -->|"No"| K3{"Email exists
    as Email account?"}
    K3 -->|"No"| K5["โœ… Allow Apple registration"]
    K3 -->|"Yes"| K7["โœ… Connect existing
    Email account with Apple"]

    L --> L1{"Email linked to
    Facebook or X?"}
    L1 -->|"Yes"| L4["PROFILE_LINKED_TO_FACEBOOK / X"]
    L1 -->|"No"| L2{"Apple profile OR
    email profile exists?"}
    L2 -->|"No"| L3["USER_NOT_FOUND"]
    L2 -->|"Yes"| L5["โœ… Login successful"]
        

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

Registration
  • No email verification required
  • Prevents duplicate Facebook accounts
  • Blocks if email exists on Email or Google
Login
  • One authentication method per email, enforced
  • Only succeeds if the user originally registered via Facebook

๐Ÿ…– Google Flexible linking

Registration
  • Prevents duplicate Google accounts
  • Blocks if email exists on Facebook or X
  • Connects to an existing Email or Apple account automatically
Login
  • 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

Registration
  • No email verification required
  • Prevents duplicate X accounts
  • Blocks if email exists on Email, Google, or Facebook
Login
  • 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

Registration
  • Deduplicated by Apple's sub provider 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)
Login
  • 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

Registration
  • Blocked if email exists on Facebook or X
  • Auto-connects an existing Google or Apple account
Password reset
  • Facebook/X-only accounts never receive a reset email (silent no-op)
  • Email, Google, and Apple accounts can reset

Error codes and messages

Error codeError keyDescription
USER_ALREADY_EXISTSuser.alreadyExistsProvider account already exists
PROFILE_LINKED_TO_NON_FACEBOOKprofile.linkedToNonFacebookEmail is associated with Email/Google/X/Apple account
PROFILE_LINKED_TO_FACEBOOKprofile.linkedToFacebookEmail is associated with Facebook account
PROFILE_LINKED_TO_NON_Xprofile.linkedToNonXEmail is associated with Email/Google/Facebook/Apple account
PROFILE_LINKED_TO_Xprofile.linkedToXEmail is associated with X account
APPLE_MISSING_EMAILapple.missingEmailApple identity token did not include an email claim
USER_NOT_FOUNDuser.notFoundUser does not exist in the system
USER_INCORRECT_EMAIL_PASSuser.incorrectEmailOrPasswordUser gave incorrect email or password

Security considerations

1
Silent password reset failure

OAuth-only accounts (Facebook, X) don't receive password reset emails โ€” this prevents information disclosure about which accounts exist.

2
Provider ID validation

Every OAuth provider ID is checked for uniqueness to prevent duplicate account creation.

3
Email verification

Facebook and X registrations skip email verification but enforce strict isolation instead, blocking any cross-provider linking or takeover attempt.

4
Cross-provider protection

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.

5
Account takeover prevention

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.