Files
motovaultpro/docs/changes/ONBOARDING-FIX.md
2025-12-26 09:25:42 -06:00

6.2 KiB

Fix New User Signup Wizard Flow

Problem Summary

The new user signup wizard is broken:

  1. After Auth0 callback, users go to /garage instead of /verify-email
  2. Users can access /garage/* without verified email
  3. Onboarding flow is bypassed entirely
  4. New Requirement: Block login completely at Auth0 for unverified users

Root Causes

  1. Auth0Provider.tsx:29 - onRedirectCallback defaults to /garage without checking verification
  2. App.tsx:472-481 - Callback route just shows "Processing login..." with no routing logic
  3. App.tsx:549+ - Protected routes have no email verification check
  4. Auth0 - No rule/action blocking unverified users from logging in

Implementation Plan

Phase 1: Auth0 Configuration (Manual Step)

Auth0 Dashboard -> Actions -> Flows -> Login

Create a Post Login Action to block unverified users:

exports.onExecutePostLogin = async (event, api) => {
  if (!event.user.email_verified) {
    api.access.deny('Please verify your email address before logging in. Check your inbox for a verification link.');
  }
};

This ensures:

  • Unverified users cannot get a JWT
  • They see a clear error on the Auth0 login screen
  • They must click the verification link before logging in

Phase 2: Update Signup Flow

After signup, redirect to a "Check Your Email" page (not /verify-email)

The new flow:

  1. User submits signup form
  2. Backend creates Auth0 user (unverified)
  3. Auth0 automatically sends verification email
  4. Frontend shows "Check Your Email" page with:
    • Message: "We've sent a verification link to your email"
    • Resend button (calls public resend endpoint)
    • "Back to Login" button
  5. User clicks email link -> Auth0 marks as verified
  6. User can now login -> goes to /onboarding

Phase 3: Backend Changes

File: backend/src/features/auth/api/auth.routes.ts

  • Add POST /api/auth/resend-verification-public (no JWT required)
  • Takes email address, looks up user, resends verification

File: backend/src/features/auth/api/auth.controller.ts

  • Add resendVerificationPublic handler

File: backend/src/features/auth/domain/auth.service.ts

  • Add resendVerificationByEmail method

File: backend/src/features/auth/api/auth.routes.ts

  • Add GET /api/auth/user-status (JWT required)
  • Returns: { emailVerified, onboardingCompleted, email }

File: backend/src/core/plugins/auth.plugin.ts

  • Add /api/auth/user-status to VERIFICATION_EXEMPT_ROUTES

Phase 4: Create Callback Handler

File: frontend/src/features/auth/pages/CallbackPage.tsx (NEW)

  • Fetches user status after Auth0 callback
  • Routes based on status:
    • Not onboarded -> /onboarding
    • Onboarded -> /garage (or returnTo)
  • Note: Unverified users never reach this (blocked by Auth0)

File: frontend/src/features/auth/mobile/CallbackMobileScreen.tsx (NEW)

  • Mobile version

Phase 5: Update Auth0Provider

File: frontend/src/core/auth/Auth0Provider.tsx

Update onRedirectCallback (line 27-31):

const onRedirectCallback = (appState?: { returnTo?: string }) => {
  navigate('/callback', {
    replace: true,
    state: { returnTo: appState?.returnTo || '/garage' }
  });
};

Phase 6: Rename/Update Verify Email Page

File: frontend/src/features/auth/pages/VerifyEmailPage.tsx

  • Rename concept to "Check Your Email" page
  • Remove polling (user can't be authenticated)
  • Show static message + resend button (calls public endpoint)
  • Add "Back to Login" button

File: frontend/src/features/auth/mobile/VerifyEmailMobileScreen.tsx

  • Same changes for mobile

Phase 7: Update App.tsx Routing

File: frontend/src/App.tsx

  1. Replace callback handling (lines 472-481) with CallbackPage
  2. Add onboarding guard after authentication check
  3. Remove email verification check from frontend (Auth0 handles it)
// After isAuthenticated check:
// Fetch onboarding status
// If not onboarded -> /onboarding
// Otherwise -> proceed to /garage

Phase 8: Create Supporting Files

File: frontend/src/core/auth/useUserStatus.ts (NEW)

  • Hook for fetching user status

File: frontend/src/features/auth/api/auth.api.ts

  • Add getUserStatus()
  • Add resendVerificationPublic(email) (no auth)

Files to Modify

Auth0 (Manual Configuration)

  • Create Post Login Action to block unverified users

Backend

  • backend/src/features/auth/api/auth.routes.ts - Add endpoints
  • backend/src/features/auth/api/auth.controller.ts - Add handlers
  • backend/src/features/auth/domain/auth.service.ts - Add methods
  • backend/src/core/plugins/auth.plugin.ts - Update exempt routes

Frontend

  • frontend/src/core/auth/Auth0Provider.tsx - Fix onRedirectCallback
  • frontend/src/App.tsx - Add route guards and callback handler
  • frontend/src/features/auth/pages/CallbackPage.tsx - NEW
  • frontend/src/features/auth/mobile/CallbackMobileScreen.tsx - NEW
  • frontend/src/features/auth/pages/VerifyEmailPage.tsx - Update to static page
  • frontend/src/features/auth/mobile/VerifyEmailMobileScreen.tsx - Update
  • frontend/src/core/auth/useUserStatus.ts - NEW
  • frontend/src/features/auth/api/auth.api.ts - Add functions

New User Flow (After Fix)

1. Signup form submission
2. -> POST /api/auth/signup (creates unverified Auth0 user)
3. -> Navigate to /verify-email (static "Check Your Email" page)
4. User clicks verification link in email
5. -> Auth0 marks user as verified
6. User clicks "Login" on /verify-email page
7. -> Auth0 login succeeds (user is now verified)
8. -> /callback page fetches status
9. -> Not onboarded? -> /onboarding
10. -> Complete onboarding -> /garage

Returning User Flow

1. Login attempt (unverified) -> Auth0 blocks with error message
2. Login attempt (verified, not onboarded) -> /callback -> /onboarding
3. Login attempt (verified, onboarded) -> /callback -> /garage

Testing Checklist

  • Auth0 Action blocks unverified login with clear error
  • Signup -> check-email page -> verify via email -> login works
  • Resend verification from check-email page works
  • Verified user (no onboarding) -> onboarding wizard
  • Verified + onboarded user -> direct to garage
  • Direct URL access to /garage -> requires login
  • All flows work on mobile
  • All flows work on desktop