Authentication Flow
End-to-end authentication from registration to token refresh
Authentication Flow
Registration Flow
1. User fills RegisterForm
│
2. useAuth().register(name, email, password)
│
3. POST /api/v1/auth/register
│
4. Backend creates user + dispatches UserCreated event
│
5. Welcome email sent (Mailpit in dev, Brevo in prod)
│
6. Backend returns { token, refreshToken, userId }
│
7. authStore.setAuth(token, refreshToken)
│
8. useProfile().fetchProfile() → updates authStore.user
│
9. Router navigates to /profile
Login Flow
1. User fills LoginForm
│
2. useAuth().login(email, password)
│
3. POST /api/v1/auth/login
│
4. Backend verifies credentials
│
5. Returns { token, refreshToken }
│
6. authStore.setAuth(token, refreshToken)
│
7. fetchProfile() → updates user state
│
8. Router navigates to /profile
Social Login Flow (Firebase/Google)
1. User clicks SocialLoginButton
│
2. Firebase popup opens (Google OAuth)
│
3. User authenticates with Google
│
4. Firebase returns idToken
│
5. useAuth().socialLogin(idToken)
│
6. POST /api/v1/auth/social { idToken, provider: 'google' }
│
7. Backend verifies token with Firebase Admin SDK
│ ├── New user → creates account (emailValidated: true)
│ └── Existing user → issues new tokens
│
8. Returns { token, refreshToken, isNewUser }
│
9. authStore.setAuth() + fetchProfile()
│
10. Router navigates to /profile
Token Refresh Flow
1. API call returns 401 Unauthorized
│
2. useApi detects 401 response
│
3. POST /api/v1/auth/token/refresh { refreshToken }
│
4. Backend validates refresh token
│ ├── Valid → returns new { token, refreshToken }
│ └── Invalid/expired → returns 401
│
5a. Success:
│ ├── authStore.setAuth(newToken, newRefreshToken)
│ └── Retry original request with new token
│
5b. Failure:
├── authStore.clearAuth()
└── Redirect to /auth/login
Password Reset Flow
1. User fills ForgotPasswordForm with email
│
2. POST /api/v1/auth/forgot-password { email }
│
3. Backend always returns 202 (prevents email enumeration)
│
4. If email exists → sends reset email with tokenized link
│
5. User clicks link in email
│
6. GET /api/v1/auth/reset-password/{token}
│
7. Backend validates token, redirects to frontend:
│ {FRONTEND_RESET_PASSWORD_URL}?token={token}
│
8. User fills ResetPasswordForm with new password
│
9. POST /api/v1/auth/reset-password { token, password }
│
10. Password is changed, PasswordChanged email sent
Email Verification Flow
1. User registers → welcome email sent
│
2. Email contains validation link:
│ /api/v1/auth/validate-email/{token}
│
3. User clicks link
│
4. Backend validates token, sets emailValidated: true
│
5. Redirects to EMAIL_VALIDATION_REDIRECT_URL
│ (typically /auth/email-verified)
│
6. Frontend shows confirmation page
Session Persistence
Auth state is persisted to localStorage:
authStore.initAuth()runs on app mount (app.vue)- Reads
token,refreshToken, anduserfrom localStorage - If a token exists, sets
isAuthenticated: true - Profile is fetched to validate the token is still valid