Authentication Flows
Step-by-step walkthrough of user registration, sign-in methods, email verification, and password reset flows.
This page details the complete authentication flows - from user registration to password recovery.
User Registration
┌──────────────────────────────────────────────────────────────────┐
│ 1. User submits registration form (name, email, password) │
│ ↓ │
│ 2. System creates user record and hashes password │
│ ↓ │
│ 3. If email verification enabled: │
│ → Verification token generated and stored │
│ → Verification email sent via Resend │
│ → User cannot sign in until verified │
│ ↓ │
│ 4. If Stripe integration enabled: │
│ → Stripe customer automatically created │
│ → Customer ID linked to user account │
│ ↓ │
│ 5. User redirected to dashboard (or verification pending) │
└──────────────────────────────────────────────────────────────────┘What Happens Behind the Scenes
- Validation - Email format and password strength checked client-side
- Duplicate Check - System verifies email isn't already registered
- Password Hashing - Password securely hashed before storage
- Account Creation - User and account records created in database
- Stripe Sync - Customer created in Stripe with email for billing
- Email Sent - Verification email dispatched if enabled
Sign-In Methods
Email & Password
┌──────────────────────────────────────────────────────────────────┐
│ 1. User enters email and password │
│ ↓ │
│ 2. System validates credentials against stored hash │
│ ↓ │
│ 3. If email verification required and not verified: │
│ → Error shown with "Resend verification" option │
│ → Sign-in blocked │
│ ↓ │
│ 4. On success: │
│ → Session created in database │
│ → Session token set as HTTP-only cookie │
│ → User redirected to dashboard │
└──────────────────────────────────────────────────────────────────┘Magic Link (Passwordless)
Magic links allow users to sign in without remembering a password.
┌──────────────────────────────────────────────────────────────────┐
│ 1. User enters email only │
│ ↓ │
│ 2. System generates time-limited token (5 minutes) │
│ ↓ │
│ 3. Magic link email sent to user │
│ ↓ │
│ 4. User clicks link in email │
│ ↓ │
│ 5. System validates token: │
│ → Valid: Session created, redirect to dashboard │
│ → Expired/Invalid: Error shown, request new link │
└──────────────────────────────────────────────────────────────────┘Token Expiry
Magic links expire after 5 minutes for security. Users can request a new link if theirs expires.
Google OAuth
┌──────────────────────────────────────────────────────────────────┐
│ 1. User clicks "Continue with Google" │
│ ↓ │
│ 2. Redirected to Google consent screen │
│ ↓ │
│ 3. User grants permission │
│ ↓ │
│ 4. Redirected back with authorization code │
│ ↓ │
│ 5. System exchanges code for tokens │
│ ↓ │
│ 6. User lookup/creation: │
│ → New user: Account created with Google profile │
│ → Existing user: OAuth linked to existing account │
│ ↓ │
│ 7. Session created, redirect to dashboard │
└──────────────────────────────────────────────────────────────────┘Account Linking: If a user signs up with email/password first, then later signs in with Google using the same email, the accounts are automatically linked.
Email Verification
Email verification ensures users own the email address they registered with.
┌──────────────────────────────────────────────────────────────────┐
│ Trigger: Automatically sent on registration (when enabled) │
│ ↓ │
│ 1. Verification token generated with expiration │
│ ↓ │
│ 2. Email sent containing verification link │
│ ↓ │
│ 3. User clicks link in email │
│ ↓ │
│ 4. System validates token: │
│ → Checks token exists and hasn't expired │
│ → Verifies token matches the email │
│ ↓ │
│ 5. On success: │
│ → User's emailVerified flag set to true │
│ → Token deleted from database │
│ → User automatically signed in │
└──────────────────────────────────────────────────────────────────┘Resending Verification
If the verification email is lost or expires:
- User attempts to sign in
- System detects unverified email
- Error displayed with "Resend verification email" button
- New token generated and email sent
Password Reset
Step 1: Request Reset (/forgot-password)
┌──────────────────────────────────────────────────────────────────┐
│ 1. User enters email address │
│ ↓ │
│ 2. System looks up user by email │
│ → If not found: Silently continues (prevents enumeration) │
│ → If found: Reset token generated │
│ ↓ │
│ 3. Password reset email sent (if user exists) │
│ ↓ │
│ 4. Success message shown regardless of email existence │
│ "If an account exists, you'll receive a reset link" │
└──────────────────────────────────────────────────────────────────┘Security: Email Enumeration Protection
The system always shows the same success message whether or not the email exists. This prevents attackers from discovering which emails have accounts.
Step 2: Reset Password (/reset-password)
┌──────────────────────────────────────────────────────────────────┐
│ 1. User clicks link in email (contains token) │
│ ↓ │
│ 2. System validates token: │
│ → Missing: Error with link to request new token │
│ → Expired: Redirect to forgot-password page │
│ → Invalid: Redirect to forgot-password page │
│ → Valid: Show password reset form │
│ ↓ │
│ 3. User enters new password │
│ → Password strength indicator shows in real-time │
│ → Requirements validated as user types │
│ ↓ │
│ 4. On submit: │
│ → New password hashed and saved │
│ → Reset token deleted (single-use) │
│ → User redirected to sign-in page │
└──────────────────────────────────────────────────────────────────┘Password Requirements
The reset form enforces the same requirements as registration:
| Requirement | Validation |
|---|---|
| Minimum 8 characters | Real-time length check |
| At least one uppercase | [A-Z] pattern match |
| At least one lowercase | [a-z] pattern match |
| At least one number | [0-9] pattern match |
The password strength indicator provides immediate feedback:
- Very Weak - Minimal requirements
- Weak - Missing some complexity
- Fair - Meets basic requirements
- Strong - Good length and variety
- Very Strong - Excellent security
Session Management
Session Creation
When a user successfully authenticates:
-
Session Record - Created in database with:
- Unique session ID
- User ID reference
- Session token (for cookie)
- Expiration timestamp
- Client IP address
- User agent string
-
Cookie Set - HTTP-only cookie containing session token
-
Client Update -
useSessionhook receives new session data
Session Validation
On each authenticated request:
- Session token extracted from cookie
- Token looked up in database
- Expiration checked
- If valid, request proceeds with user context
- If invalid/expired, user redirected to sign-in
Session Termination
Sessions end when:
- User Signs Out - Session record deleted, cookie cleared
- Session Expires - Automatically rejected on next request
- Manual Revocation - Admin or user deletes session from database
Next Steps
- Configuration - Enable/disable features and customize behavior
- Email System - Customize authentication email templates
Authentication Overview
Complete identity management with Better Auth - supporting email/password, magic links, Google OAuth, email verification, and Stripe integration.
Authentication Configuration
Configure authentication methods, OAuth providers, email verification, and customize behavior for your application.