286 lines
14 KiB
Markdown
286 lines
14 KiB
Markdown
# Authentication Flow Diagrams
|
|
|
|
## Cookie Isolation Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Browser │
|
|
│ │
|
|
│ ┌─────────────────────┐ ┌─────────────────────┐ │
|
|
│ │ Admin Area │ │ Vendor Area │ │
|
|
│ │ /admin/* │ │ /vendor/* │ │
|
|
│ │ │ │ │ │
|
|
│ │ 🍪 admin_token │ │ 🍪 vendor_token │ │
|
|
│ │ Path: /admin │ │ Path: /vendor │ │
|
|
│ └─────────────────────┘ └─────────────────────┘ │
|
|
│ │ │ │
|
|
│ ├───────────────────────────┤ │
|
|
│ │ ❌ No Cookie Mixing │ │
|
|
│ │ │ │
|
|
└───────────┼───────────────────────────┼──────────────────────┘
|
|
│ │
|
|
▼ ▼
|
|
┌───────────────────────┐ ┌───────────────────────┐
|
|
│ Admin Backend │ │ Vendor Backend │
|
|
│ /admin/* │ │ /vendor/* │
|
|
│ │ │ │
|
|
│ ✅ admin_token │ │ ✅ vendor_token │
|
|
│ ❌ vendor_token │ │ ❌ admin_token │
|
|
└───────────────────────┘ └───────────────────────┘
|
|
```
|
|
|
|
## Login Flow - Admin
|
|
|
|
```
|
|
┌──────────┐
|
|
│ Browser │
|
|
└──────────┘
|
|
│
|
|
│ POST /api/v1/admin/auth/login
|
|
│ { username, password }
|
|
▼
|
|
┌─────────────────────────┐
|
|
│ Admin Auth Endpoint │
|
|
│ │
|
|
│ 1. Validate credentials│
|
|
│ 2. Check role == admin │
|
|
│ 3. Generate JWT │
|
|
└─────────────────────────┘
|
|
│
|
|
│ Set-Cookie: admin_token=<JWT>; Path=/admin; HttpOnly; SameSite=Lax
|
|
│ Response: { access_token, user }
|
|
▼
|
|
┌──────────┐
|
|
│ Browser │──────────────────────────────────────┐
|
|
│ │ │
|
|
│ 🍪 admin_token (Path=/admin) │
|
|
│ 💾 localStorage.access_token │
|
|
└──────────┘ │
|
|
│ │
|
|
├── Navigate to /admin/dashboard ────────────┤
|
|
│ (Cookie sent automatically) │
|
|
│ │
|
|
└── API call to /api/v1/admin/vendors ───────┤
|
|
(Authorization: Bearer <token>) │
|
|
│
|
|
┌──────────────▼──────────────┐
|
|
│ get_current_admin_user() │
|
|
│ │
|
|
│ 1. Check Auth header │
|
|
│ 2. Check admin_token cookie │
|
|
│ 3. Validate JWT │
|
|
│ 4. Verify role == admin │
|
|
│ ✅ Return User │
|
|
└──────────────────────────────┘
|
|
```
|
|
|
|
## Login Flow - Vendor
|
|
|
|
```
|
|
┌──────────┐
|
|
│ Browser │
|
|
└──────────┘
|
|
│
|
|
│ POST /api/v1/vendor/auth/login
|
|
│ { username, password }
|
|
▼
|
|
┌─────────────────────────┐
|
|
│ Vendor Auth Endpoint │
|
|
│ │
|
|
│ 1. Validate credentials│
|
|
│ 2. Block if admin │──────> ❌ "Admins cannot access vendor portal"
|
|
│ 3. Check vendor access │
|
|
│ 4. Generate JWT │
|
|
└─────────────────────────┘
|
|
│
|
|
│ Set-Cookie: vendor_token=<JWT>; Path=/vendor; HttpOnly; SameSite=Lax
|
|
│ Response: { access_token, user, vendor }
|
|
▼
|
|
┌──────────┐
|
|
│ Browser │──────────────────────────────────────┐
|
|
│ │ │
|
|
│ 🍪 vendor_token (Path=/vendor) │
|
|
│ 💾 localStorage.access_token │
|
|
└──────────┘ │
|
|
│ │
|
|
├── Navigate to /vendor/ACME/dashboard ──────┤
|
|
│ (Cookie sent automatically) │
|
|
│ │
|
|
└── API call to /api/v1/vendor/ACME/products ┤
|
|
(Authorization: Bearer <token>) │
|
|
│
|
|
┌──────────────▼──────────────┐
|
|
│ get_current_vendor_user() │
|
|
│ │
|
|
│ 1. Check Auth header │
|
|
│ 2. Check vendor_token cookie│
|
|
│ 3. Validate JWT │
|
|
│ 4. Block if admin │──> ❌ Error
|
|
│ 5. Verify vendor access │
|
|
│ ✅ Return User │
|
|
└──────────────────────────────┘
|
|
```
|
|
|
|
## Security Boundary Enforcement
|
|
|
|
```
|
|
┌─────────────────────┐
|
|
│ Request Comes In │
|
|
└──────────┬──────────┘
|
|
│
|
|
┌──────────▼──────────┐
|
|
│ What's the path? │
|
|
└──────────┬──────────┘
|
|
│
|
|
┌───────────────┼───────────────┐
|
|
│ │ │
|
|
Starts with Starts with Starts with
|
|
/admin/* /vendor/* /api/*
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
|
│ Check for: │ │ Check for: │ │ Check for: │
|
|
│ - admin_token │ │ - vendor_token │ │ - Authorization │
|
|
│ cookie │ │ cookie │ │ header │
|
|
│ - OR Auth header │ │ - OR Auth header │ │ (required) │
|
|
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
|
│ Validate: │ │ Validate: │ │ Validate: │
|
|
│ - JWT valid │ │ - JWT valid │ │ - JWT valid │
|
|
│ - User active │ │ - User active │ │ - User active │
|
|
│ - Role = admin │ │ - Role != admin │ │ - Any role │
|
|
│ │ │ - Has vendor │ │ (depends on │
|
|
│ │ │ access │ │ endpoint) │
|
|
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
✅ Allowed ✅ Allowed ✅ Allowed
|
|
```
|
|
|
|
## Cross-Context Prevention
|
|
|
|
### ❌ What's Blocked
|
|
|
|
```
|
|
Admin trying to access vendor route:
|
|
┌──────────────────────────────────────────┐
|
|
│ User: admin@example.com (role: admin) │
|
|
│ Token: Valid JWT with admin role │
|
|
│ Request: GET /vendor/ACME/dashboard │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────┐
|
|
│ get_current_vendor_ │
|
|
│ from_cookie_or_header │
|
|
└───────────┬───────────┘
|
|
│
|
|
▼
|
|
Check: role == "admin"?
|
|
│
|
|
▼ Yes
|
|
❌ InsufficientPermissionsException
|
|
"Vendor access only - admins cannot use vendor portal"
|
|
```
|
|
|
|
```
|
|
Vendor trying to access admin route:
|
|
┌──────────────────────────────────────────┐
|
|
│ User: vendor@acme.com (role: vendor) │
|
|
│ Token: Valid JWT with vendor role │
|
|
│ Request: GET /admin/dashboard │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────┐
|
|
│ get_current_admin_ │
|
|
│ from_cookie_or_header │
|
|
└───────────┬───────────┘
|
|
│
|
|
▼
|
|
Check: role == "admin"?
|
|
│
|
|
▼ No
|
|
❌ AdminRequiredException
|
|
"Admin privileges required"
|
|
```
|
|
|
|
```
|
|
Admin cookie sent to vendor route:
|
|
┌──────────────────────────────────────────┐
|
|
│ Cookie: admin_token=<JWT> (Path=/admin) │
|
|
│ Request: GET /vendor/ACME/dashboard │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
Browser checks cookie path
|
|
│
|
|
▼
|
|
Path /vendor does NOT match /admin
|
|
│
|
|
▼
|
|
❌ Cookie NOT sent
|
|
Request has no authentication
|
|
│
|
|
▼
|
|
❌ InvalidTokenException
|
|
"Vendor authentication required"
|
|
```
|
|
|
|
## Cookie Lifecycle
|
|
|
|
```
|
|
LOGIN
|
|
│
|
|
├── Server generates JWT
|
|
├── Server sets cookie:
|
|
│ • Name: admin_token or vendor_token
|
|
│ • Value: JWT
|
|
│ • Path: /admin or /vendor
|
|
│ • HttpOnly: true
|
|
│ • Secure: true (production)
|
|
│ • SameSite: Lax
|
|
│ • Max-Age: matches JWT expiry
|
|
│
|
|
└── Server returns JWT in response body
|
|
└── Client stores in localStorage (optional)
|
|
|
|
PAGE NAVIGATION
|
|
│
|
|
├── Browser automatically includes cookie
|
|
│ if path matches
|
|
│
|
|
├── Server reads cookie
|
|
├── Server validates JWT
|
|
└── Server returns page or 401
|
|
|
|
API CALL
|
|
│
|
|
├── Client reads token from localStorage
|
|
├── Client adds Authorization header
|
|
│ Authorization: Bearer <JWT>
|
|
│
|
|
├── Server reads header
|
|
├── Server validates JWT
|
|
└── Server returns data or 401
|
|
|
|
LOGOUT
|
|
│
|
|
├── Client calls logout endpoint
|
|
├── Server clears cookie:
|
|
│ response.delete_cookie(name, path)
|
|
│
|
|
└── Client clears localStorage
|
|
localStorage.removeItem('access_token')
|
|
```
|
|
|
|
## Key Takeaways
|
|
|
|
1. **Cookie Path Isolation** = No cross-context cookies
|
|
2. **Role Checking** = Admins blocked from vendor routes
|
|
3. **Dual Auth Support** = Cookies for pages, headers for API
|
|
4. **Security First** = HttpOnly, Secure, SameSite protection
|
|
5. **Clear Boundaries** = Each context is completely isolated
|