Some checks failed
- Add Development URL Quick Reference section to url-routing overview with all login URLs, entry points, and full examples - Replace /shop/ path segments with /storefront/ across 50 docs files - Update file references: shop_pages.py → storefront_pages.py, templates/shop/ → templates/storefront/, api/v1/shop/ → api/v1/storefront/ - Preserve domain references (orion.shop) and /store/ staff dashboard paths - Archive docs left unchanged (historical) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
391 lines
21 KiB
Markdown
391 lines
21 KiB
Markdown
# Authentication Flow Diagrams
|
|
|
|
## Cookie Isolation Architecture
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
│ Browser │
|
|
│ │
|
|
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
|
|
│ │ Admin Area │ │ Store Area │ │ Storefront Area │ │
|
|
│ │ /admin/* │ │ /store/* │ │ /storefront/* │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ 🍪 admin_token │ │ 🍪 store_token │ │ 🍪 customer_ │ │
|
|
│ │ Path: /admin │ │ Path: /store │ │ token │ │
|
|
│ │ │ │ │ │ Path: /storefront │ │
|
|
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
|
|
│ │ │ │ │
|
|
│ ├──────────────────────┼─────────────────────┤ │
|
|
│ │ ❌ No Cookie Mixing │ │
|
|
│ │ │ │ │
|
|
└───────────┼──────────────────────┼─────────────────────┼─────────────────────┘
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
|
│ Admin Backend │ │ Store Backend │ │ Storefront Backend │
|
|
│ /admin/* │ │ /store/* │ │ /storefront/* │
|
|
│ │ │ │ │ │
|
|
│ ✅ admin_token │ │ ✅ store_token │ │ ✅ customer_ │
|
|
│ ❌ store_token │ │ ❌ admin_token │ │ token │
|
|
│ ❌ customer_ │ │ ❌ customer_ │ │ ❌ admin_token │
|
|
│ token │ │ token │ │ ❌ store_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/stores ───────┤
|
|
(Authorization: Bearer <token>) │
|
|
│
|
|
┌────────────────────────────────────────┐
|
|
│ HTML: get_current_admin_from_ │
|
|
│ cookie_or_header() │
|
|
│ API: get_current_admin_api() │
|
|
│ │
|
|
│ 1. Check Auth header │
|
|
│ 2. Check admin_token cookie (HTML)│
|
|
│ 3. Validate JWT │
|
|
│ 4. Verify role == admin │
|
|
│ ✅ Return User │
|
|
└────────────────────────────────────┘
|
|
```
|
|
|
|
## Login Flow - Store
|
|
|
|
```
|
|
┌──────────┐
|
|
│ Browser │
|
|
└──────────┘
|
|
│
|
|
│ POST /api/v1/store/auth/login
|
|
│ { username, password }
|
|
▼
|
|
┌─────────────────────────┐
|
|
│ Store Auth Endpoint │
|
|
│ │
|
|
│ 1. Validate credentials│
|
|
│ 2. Block if admin │──────> ❌ "Admins cannot access store portal"
|
|
│ 3. Check store access │
|
|
│ 4. Generate JWT │
|
|
└─────────────────────────┘
|
|
│
|
|
│ Set-Cookie: store_token=<JWT>; Path=/store; HttpOnly; SameSite=Lax
|
|
│ Response: { access_token, user, store }
|
|
▼
|
|
┌──────────┐
|
|
│ Browser │──────────────────────────────────────┐
|
|
│ │ │
|
|
│ 🍪 store_token (Path=/store) │
|
|
│ 💾 localStorage.access_token │
|
|
└──────────┘ │
|
|
│ │
|
|
├── Navigate to /store/ACME/dashboard ──────┤
|
|
│ (Cookie sent automatically) │
|
|
│ │
|
|
└── API call to /api/v1/store/ACME/products ┤
|
|
(Authorization: Bearer <token>) │
|
|
│
|
|
┌────────────────────────────────────────┐
|
|
│ HTML: get_current_store_from_ │
|
|
│ cookie_or_header() │
|
|
│ API: get_current_store_api() │
|
|
│ │
|
|
│ 1. Check Auth header │
|
|
│ 2. Check store_token cookie (HTML)│
|
|
│ 3. Validate JWT │
|
|
│ 4. Block if admin │──> ❌ Error
|
|
│ 5. Verify store access │
|
|
│ ✅ Return User │
|
|
└────────────────────────────────────┘
|
|
```
|
|
|
|
## Login Flow - Customer (Storefront)
|
|
|
|
```
|
|
┌──────────┐
|
|
│ Browser │
|
|
└──────────┘
|
|
│
|
|
│ POST /api/v1/storefront/auth/login
|
|
│ { email, password }
|
|
▼
|
|
┌─────────────────────────┐
|
|
│ Customer Auth Endpoint │
|
|
│ │
|
|
│ 1. Validate credentials│
|
|
│ 2. Check role = customer│
|
|
│ 3. Generate JWT │
|
|
└─────────────────────────┘
|
|
│
|
|
│ Set-Cookie: customer_token=<JWT>; Path=/storefront; HttpOnly; SameSite=Lax
|
|
│ Response: { access_token, user }
|
|
▼
|
|
┌──────────┐
|
|
│ Browser │──────────────────────────────────────┐
|
|
│ │ │
|
|
│ 🍪 customer_token (Path=/storefront) │
|
|
│ 💾 localStorage.access_token │
|
|
└──────────┘ │
|
|
│ │
|
|
├── Navigate to /storefront/account/dashboard ─────┤
|
|
│ (Cookie sent automatically) │
|
|
│ │
|
|
└── API call to /api/v1/storefront/orders ─────────┤
|
|
(Authorization: Bearer <token>) │
|
|
│
|
|
┌────────────────────────────────────────┐
|
|
│ HTML: get_current_customer_from_ │
|
|
│ cookie_or_header() │
|
|
│ API: get_current_customer_api() │
|
|
│ │
|
|
│ 1. Check Auth header │
|
|
│ 2. Check customer_token cookie (HTML)│
|
|
│ 3. Validate JWT │
|
|
│ 4. Verify role = customer │
|
|
│ ✅ Return User │
|
|
└────────────────────────────────────┘
|
|
```
|
|
|
|
## Security Boundary Enforcement
|
|
|
|
```
|
|
┌─────────────────────┐
|
|
│ Request Comes In │
|
|
└──────────┬──────────┘
|
|
│
|
|
┌──────────▼──────────┐
|
|
│ What's the path? │
|
|
└──────────┬──────────┘
|
|
│
|
|
┌───────────────────────────┼───────────────────────────┐
|
|
│ │ │ │ │
|
|
Starts with Starts with Starts with Starts with Starts with
|
|
/admin/* /store/* /storefront/* /api/* (public)
|
|
│ │ │ │ │
|
|
▼ ▼ ▼ ▼ ▼
|
|
┌────────────────┐┌────────────────┐┌────────────────┐┌────────────────┐┌────────────────┐
|
|
│ Check for: ││ Check for: ││ Check for: ││ Check for: ││ No Auth │
|
|
│ - admin_token ││ - store_token ││ - customer_ ││ - Authorization││ Required │
|
|
│ cookie ││ cookie ││ token cookie ││ header ││ │
|
|
│ - OR Auth ││ - OR Auth ││ - OR Auth ││ (required) ││ Public pages │
|
|
│ header ││ header ││ header ││ ││ & assets │
|
|
└────────┬───────┘└────────┬───────┘└────────┬───────┘└────────┬───────┘└────────────────┘
|
|
│ │ │ │
|
|
▼ ▼ ▼ ▼
|
|
┌────────────────┐┌────────────────┐┌────────────────┐┌────────────────┐
|
|
│ Validate: ││ Validate: ││ Validate: ││ Validate: │
|
|
│ - JWT valid ││ - JWT valid ││ - JWT valid ││ - JWT valid │
|
|
│ - User active ││ - User active ││ - User active ││ - User active │
|
|
│ - Role = admin ││ - Role != admin││ - Role = ││ - Any role │
|
|
│ ││ - Has store ││ customer ││ (depends on │
|
|
│ ││ access ││ ││ endpoint) │
|
|
└────────┬───────┘└────────┬───────┘└────────┬───────┘└────────┬───────┘
|
|
│ │ │ │
|
|
▼ ▼ ▼ ▼
|
|
✅ Allowed ✅ Allowed ✅ Allowed ✅ Allowed
|
|
```
|
|
|
|
## Cross-Context Prevention
|
|
|
|
### ❌ What's Blocked
|
|
|
|
```
|
|
Admin trying to access store route:
|
|
┌──────────────────────────────────────────┐
|
|
│ User: admin@example.com (role: admin) │
|
|
│ Token: Valid JWT with admin role │
|
|
│ Request: GET /store/ACME/dashboard │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────┐
|
|
│ get_current_store_ │
|
|
│ from_cookie_or_header │
|
|
└───────────┬───────────┘
|
|
│
|
|
▼
|
|
Check: role == "admin"?
|
|
│
|
|
▼ Yes
|
|
❌ InsufficientPermissionsException
|
|
"Store access only - admins cannot use store portal"
|
|
```
|
|
|
|
```
|
|
Store trying to access admin route:
|
|
┌──────────────────────────────────────────┐
|
|
│ User: store@acme.com (role: store) │
|
|
│ Token: Valid JWT with store role │
|
|
│ Request: GET /admin/dashboard │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────┐
|
|
│ get_current_admin_ │
|
|
│ from_cookie_or_header │
|
|
└───────────┬───────────┘
|
|
│
|
|
▼
|
|
Check: role == "admin"?
|
|
│
|
|
▼ No
|
|
❌ AdminRequiredException
|
|
"Admin privileges required"
|
|
```
|
|
|
|
```
|
|
Admin cookie sent to store route:
|
|
┌──────────────────────────────────────────┐
|
|
│ Cookie: admin_token=<JWT> (Path=/admin) │
|
|
│ Request: GET /store/ACME/dashboard │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
Browser checks cookie path
|
|
│
|
|
▼
|
|
Path /store does NOT match /admin
|
|
│
|
|
▼
|
|
❌ Cookie NOT sent
|
|
Request has no authentication
|
|
│
|
|
▼
|
|
❌ InvalidTokenException
|
|
"Store authentication required"
|
|
```
|
|
|
|
```
|
|
Customer trying to access admin route:
|
|
┌──────────────────────────────────────────┐
|
|
│ User: customer@example.com (role: customer)│
|
|
│ Token: Valid JWT with customer role │
|
|
│ Request: GET /admin/dashboard │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────┐
|
|
│ get_current_admin_ │
|
|
│ from_cookie_or_header │
|
|
└───────────┬───────────┘
|
|
│
|
|
▼
|
|
Check: role == "admin"?
|
|
│
|
|
▼ No
|
|
❌ AdminRequiredException
|
|
"Admin privileges required"
|
|
```
|
|
|
|
```
|
|
Customer cookie sent to storefront route (allowed):
|
|
┌──────────────────────────────────────────┐
|
|
│ Cookie: customer_token=<JWT> (Path=/storefront)│
|
|
│ Request: GET /storefront/account/orders │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
Browser checks cookie path
|
|
│
|
|
▼
|
|
Path /storefront matches /storefront
|
|
│
|
|
▼
|
|
✅ Cookie SENT automatically
|
|
│
|
|
▼
|
|
┌───────────────────────┐
|
|
│ get_current_customer_ │
|
|
│ from_cookie_or_header │
|
|
└───────────┬───────────┘
|
|
│
|
|
▼
|
|
✅ Customer authenticated
|
|
Page loads successfully
|
|
```
|
|
|
|
## Cookie Lifecycle
|
|
|
|
```
|
|
LOGIN
|
|
│
|
|
├── Server generates JWT
|
|
├── Server sets cookie:
|
|
│ • Name: admin_token, store_token, or customer_token
|
|
│ • Value: JWT
|
|
│ • Path: /admin, /store, or /storefront (context-specific)
|
|
│ • 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** = Three separate cookies (admin_token, store_token, customer_token) with path-based isolation
|
|
2. **Role Checking** = Strict role validation at each boundary (admin, store, customer)
|
|
3. **Dual Auth Support** = Cookies for HTML pages, headers for API endpoints
|
|
4. **Security First** = HttpOnly, Secure, SameSite protection on all cookies
|
|
5. **Clear Boundaries** = Each context (admin/store/storefront) is completely isolated
|
|
6. **Three User Types** = Admins manage platform, stores manage stores, customers shop
|