Skip to content

Instantly share code, notes, and snippets.

@Jimgerneer
Last active March 11, 2026 19:39
Show Gist options
  • Select an option

  • Save Jimgerneer/6560739fcd431038f46457a5f17747b5 to your computer and use it in GitHub Desktop.

Select an option

Save Jimgerneer/6560739fcd431038f46457a5f17747b5 to your computer and use it in GitHub Desktop.
Email Verification Error Handling — Decision Flow

Email Verification Error Handling Flow

Problem

The current VerifyEmail.tsx catch block is generic — it shows a toast and redirects to /signin regardless of the error type or user state. This creates a poor experience in several scenarios.

Cases This Solves

  1. User clicks a verification link after already being verified — e.g., they verified via one link but later click an older one from their inbox. Instead of showing a confusing error, the system detects they're already verified and sends them home.

  2. User clicks a stale verification link (expired oobCode) — common when a user hits "resend verification email" multiple times, generating multiple links. Older links become invalid. Instead of a dead-end error, the system guides them to request a fresh link.

Decision Flow (User)

  flowchart TD
      A["User clicks email verification link"] --> B{"Link valid?"}

      B -->|Yes| C["Email verified successfully"]
      C --> D["Taken to Home"]

      B -->|No| E{"Already signed in?"}

      E -->|Yes| F{"Email already verified?"}
      F -->|Yes| G["Taken to Home"]
      F -->|No| H["Shown error: previous link is no longer valid on existing Verify email page"]

      E -->|No| I["Redirected to Sign In"]
      I --> J["User signs in"]
      J --> K{"Email already verified?"}
      K -->|Yes| G
      K -->|No| H

      H --> L["User requests new verification email"]
      L --> M["New email sent"]
      M --> A
Loading

Decision Flow (Technical)

flowchart TD
    A["User clicks email verification link"] --> B["applyActionCode(auth, oobCode)"]
    B -->|Success| C["Reload user, show success alert"]
    C --> D["Redirect to /home"]

    B -->|Error: invalid/expired oobCode| E["await auth.currentUser?.reload()"]
    E --> F{"auth.currentUser exists?"}

    F -->|Yes| G{"currentUser.emailVerified?"}
    G -->|Yes| H["Clear signup state from sessionStorage"]
    H --> D

    G -->|No| I["Set oobCode error flag in sessionStorage"]
    I --> J["Redirect to /signup\n(AuthProvider routes to email verification step)"]

    F -->|No| K["Set oobCode error flag in sessionStorage"]
    K --> L["Redirect to /signin"]
    L --> M["User signs in"]
    M --> N["AuthProvider: reload + check emailVerified"]
    N -->|Verified| O["Clear signup state + oobCode error flag"]
    O --> D
    N -->|Not verified| J

    J --> P["EmailVerificationForm detects oobCode error flag"]
    P --> Q["Show error messaging:\n'Your previous verification link is no longer valid.\nPlease request a new one.'"]
    Q --> R["User clicks Send Email"]
    R --> S["sendEmailVerification(auth.currentUser)"]
    S --> A
Loading

Implementation Summary

File Change
VerifyEmail.tsx Rewrite catch block: reload() → check session → check emailVerified → set sessionStorage flag → redirect accordingly
EmailVerificationForm.tsx On mount, check for oobCode error flag in sessionStorage. If present, show error messaging and clear the flag
AuthProvider.tsx In post-signin onAuthStateChanged, check for oobCode error flag + emailVerified — if verified, clear both flags and proceed to home
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment