Files
orion/docs/api/authentication.md

1054 lines
28 KiB
Markdown

# Authentication System Documentation
**Version:** 1.0
**Last Updated:** November 2025
**Audience:** Development Team & API Consumers
---
## Table of Contents
1. [System Overview](#system-overview)
2. [Architecture](#architecture)
3. [Authentication Contexts](#authentication-contexts)
4. [Implementation Guide](#implementation-guide)
5. [API Reference](#api-reference)
6. [Security Model](#security-model)
7. [Testing Guidelines](#testing-guidelines)
8. [Troubleshooting](#troubleshooting)
9. [Best Practices](#best-practices)
---
## System Overview
The Wizamart platform uses a **context-based authentication system** with three isolated security domains:
- **Admin Portal** - Platform administration and management
- **Vendor Portal** - Multi-tenant shop management
- **Customer Shop** - Public storefront and customer accounts
Each context uses **dual authentication** supporting both cookie-based (for HTML pages) and header-based (for API calls) authentication with complete isolation between contexts.
### Key Features
- **Cookie Path Isolation** - Separate cookies per context prevent cross-context access
- **Role-Based Access Control** - Strict enforcement of user roles
- **JWT Token Authentication** - Stateless, secure token-based auth
- **HTTP-Only Cookies** - XSS protection for browser sessions
- **CSRF Protection** - SameSite cookie attribute
- **Comprehensive Logging** - Full audit trail of authentication events
---
## Architecture
### Authentication Flow
```
┌─────────────────────────────────────────────────────┐
│ Client Request │
└─────────────────┬───────────────────────────────────┘
┌───────▼────────┐
│ Route Handler │
└───────┬────────┘
┌───────▼────────────────────────────────┐
│ Authentication Dependency │
│ (from app/api/deps.py) │
└───────┬────────────────────────────────┘
┌─────────────┼─────────────┐
│ │ │
┌───▼───┐ ┌────▼────┐ ┌───▼────┐
│Cookie │ │ Header │ │ None │
└───┬───┘ └────┬────┘ └───┬────┘
│ │ │
└────────┬───┴────────────┘
┌──────▼───────┐
│ Validate JWT │
└──────┬───────┘
┌──────▼──────────┐
│ Check User Role │
└──────┬──────────┘
┌────────┴─────────┐
│ │
┌───▼────┐ ┌─────▼──────┐
│Success │ │ Auth Error │
│Return │ │ 401/403 │
│User │ └────────────┘
└────────┘
```
### Cookie Isolation
Each authentication context uses a separate cookie with path restrictions:
| Context | Cookie Name | Cookie Path | Access Scope |
|----------|------------------|-------------|--------------|
| Admin | `admin_token` | `/admin` | Admin routes only |
| Vendor | `vendor_token` | `/vendor` | Vendor routes only |
| Customer | `customer_token` | `/shop` | Shop routes only |
**Browser Behavior:**
- When requesting `/admin/*`, browser sends `admin_token` cookie only
- When requesting `/vendor/*`, browser sends `vendor_token` cookie only
- When requesting `/shop/*`, browser sends `customer_token` cookie only
This prevents cookie leakage between contexts.
---
## Authentication Contexts
### 1. Admin Context
**Routes:** `/admin/*`
**Role:** `admin`
**Cookie:** `admin_token` (path=/admin)
**Purpose:** Platform administration, vendor management, system configuration.
**Access Control:**
- ✅ Admin users only
- ❌ Vendor users blocked
- ❌ Customer users blocked
**Login Endpoint:**
```
POST /api/v1/admin/auth/login
```
**Example Request:**
```bash
curl -X POST http://localhost:8000/api/v1/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
```
**Example Response:**
```json
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"user": {
"id": 1,
"username": "admin",
"email": "admin@example.com",
"role": "admin",
"is_active": true
}
}
```
Additionally, sets cookie:
```
Set-Cookie: admin_token=<JWT>; Path=/admin; HttpOnly; Secure; SameSite=Lax
```
### 2. Vendor Context
**Routes:** `/vendor/*`
**Role:** `vendor`
**Cookie:** `vendor_token` (path=/vendor)
**Purpose:** Vendor shop management, product catalog, orders, team management.
**Access Control:**
- ❌ Admin users blocked (admins use admin portal for vendor management)
- ✅ Vendor users (owners and team members)
- ❌ Customer users blocked
**Login Endpoint:**
```
POST /api/v1/vendor/auth/login
```
**Example Request:**
```bash
curl -X POST http://localhost:8000/api/v1/vendor/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"vendor_owner","password":"vendor123"}'
```
**Example Response:**
```json
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"user": {
"id": 2,
"username": "vendor_owner",
"email": "owner@vendorshop.com",
"role": "vendor",
"is_active": true
},
"vendor": {
"id": 1,
"vendor_code": "ACME",
"name": "ACME Store"
},
"vendor_role": "owner"
}
```
Additionally, sets cookie:
```
Set-Cookie: vendor_token=<JWT>; Path=/vendor; HttpOnly; Secure; SameSite=Lax
```
### 3. Customer Context
**Routes:** `/shop/account/*` (authenticated), `/shop/*` (public)
**Role:** `customer`
**Cookie:** `customer_token` (path=/shop)
**Purpose:** Product browsing (public), customer accounts, orders, profile management.
**Access Control:**
- **Public Routes** (`/shop/products`, `/shop/cart`, etc.):
- ✅ Anyone can access (no authentication)
- **Account Routes** (`/shop/account/*`):
- ❌ Admin users blocked
- ❌ Vendor users blocked
- ✅ Customer users only
**Login Endpoint:**
```
POST /api/v1/public/vendors/{vendor_id}/customers/login
```
**Example Request:**
```bash
curl -X POST http://localhost:8000/api/v1/public/vendors/1/customers/login \
-H "Content-Type: application/json" \
-d '{"username":"customer","password":"customer123"}'
```
**Example Response:**
```json
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"user": {
"id": 100,
"email": "customer@example.com",
"customer_number": "CUST-001",
"is_active": true
}
}
```
Additionally, sets cookie:
```
Set-Cookie: customer_token=<JWT>; Path=/shop; HttpOnly; Secure; SameSite=Lax
```
---
## Implementation Guide
### Module Structure
```
app/api/
├── deps.py # Authentication dependencies
├── v1/
├── admin/
│ └── auth.py # Admin authentication endpoints
├── vendor/
│ └── auth.py # Vendor authentication endpoints
└── public/vendors/
└── auth.py # Customer authentication endpoints
```
### For HTML Pages (Server-Rendered)
Use the `*_from_cookie_or_header` functions for pages that users navigate to:
```python
from fastapi import APIRouter, Request, Depends
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from app.api.deps import (
get_current_admin_from_cookie_or_header,
get_current_vendor_from_cookie_or_header,
get_current_customer_from_cookie_or_header,
get_db
)
from models.database.user import User
router = APIRouter()
# Admin page
@router.get("/admin/dashboard", response_class=HTMLResponse)
async def admin_dashboard(
request: Request,
current_user: User = Depends(get_current_admin_from_cookie_or_header),
db: Session = Depends(get_db)
):
return templates.TemplateResponse("admin/dashboard.html", {
"request": request,
"user": current_user
})
# Vendor page
@router.get("/vendor/{vendor_code}/dashboard", response_class=HTMLResponse)
async def vendor_dashboard(
request: Request,
vendor_code: str,
current_user: User = Depends(get_current_vendor_from_cookie_or_header),
db: Session = Depends(get_db)
):
return templates.TemplateResponse("vendor/dashboard.html", {
"request": request,
"user": current_user,
"vendor_code": vendor_code
})
# Customer account page
@router.get("/shop/account/dashboard", response_class=HTMLResponse)
async def customer_dashboard(
request: Request,
current_user: User = Depends(get_current_customer_from_cookie_or_header),
db: Session = Depends(get_db)
):
return templates.TemplateResponse("shop/account/dashboard.html", {
"request": request,
"user": current_user
})
```
### For API Endpoints (JSON Responses)
Use the `*_api` functions for API endpoints to enforce header-based authentication:
```python
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.api.deps import (
get_current_admin_api,
get_current_vendor_api,
get_current_customer_api,
get_db
)
from models.database.user import User
router = APIRouter()
# Admin API
@router.post("/api/v1/admin/vendors")
def create_vendor(
vendor_data: VendorCreate,
current_user: User = Depends(get_current_admin_api),
db: Session = Depends(get_db)
):
# Only accepts Authorization header (no cookies)
# Better security - prevents CSRF attacks
return {"message": "Vendor created"}
# Vendor API
@router.post("/api/v1/vendor/{vendor_code}/products")
def create_product(
vendor_code: str,
product_data: ProductCreate,
current_user: User = Depends(get_current_vendor_api),
db: Session = Depends(get_db)
):
return {"message": "Product created"}
# Customer API
@router.post("/api/v1/shop/orders")
def create_order(
order_data: OrderCreate,
current_user: User = Depends(get_current_customer_api),
db: Session = Depends(get_db)
):
return {"message": "Order created"}
```
### For Public Routes (No Authentication)
Simply don't use any authentication dependency:
```python
@router.get("/shop/products")
async def public_products(request: Request):
# No authentication required
return templates.TemplateResponse("shop/products.html", {
"request": request
})
```
---
## API Reference
### Authentication Dependencies
All authentication functions are in `app/api/deps.py`:
#### `get_current_admin_from_cookie_or_header()`
**Purpose:** Authenticate admin users for HTML pages
**Accepts:** Cookie (`admin_token`) OR Authorization header
**Returns:** `User` object with `role="admin"`
**Raises:**
- `InvalidTokenException` - No token or invalid token
- `AdminRequiredException` - User is not admin
**Usage:**
```python
current_user: User = Depends(get_current_admin_from_cookie_or_header)
```
#### `get_current_admin_api()`
**Purpose:** Authenticate admin users for API endpoints
**Accepts:** Authorization header ONLY
**Returns:** `User` object with `role="admin"`
**Raises:**
- `InvalidTokenException` - No token or invalid token
- `AdminRequiredException` - User is not admin
**Usage:**
```python
current_user: User = Depends(get_current_admin_api)
```
#### `get_current_vendor_from_cookie_or_header()`
**Purpose:** Authenticate vendor users for HTML pages
**Accepts:** Cookie (`vendor_token`) OR Authorization header
**Returns:** `User` object with `role="vendor"`
**Raises:**
- `InvalidTokenException` - No token or invalid token
- `InsufficientPermissionsException` - User is not vendor or is admin
**Usage:**
```python
current_user: User = Depends(get_current_vendor_from_cookie_or_header)
```
#### `get_current_vendor_api()`
**Purpose:** Authenticate vendor users for API endpoints
**Accepts:** Authorization header ONLY
**Returns:** `User` object with `role="vendor"`
**Raises:**
- `InvalidTokenException` - No token or invalid token
- `InsufficientPermissionsException` - User is not vendor or is admin
**Usage:**
```python
current_user: User = Depends(get_current_vendor_api)
```
#### `get_current_customer_from_cookie_or_header()`
**Purpose:** Authenticate customer users for HTML pages
**Accepts:** Cookie (`customer_token`) OR Authorization header
**Returns:** `Customer` object
**Raises:**
- `InvalidTokenException` - No token or invalid token
- `InsufficientPermissionsException` - User is not customer (admin/vendor blocked)
**Usage:**
```python
current_customer: Customer = Depends(get_current_customer_from_cookie_or_header)
```
#### `get_current_customer_api()`
**Purpose:** Authenticate customer users for API endpoints
**Accepts:** Authorization header ONLY
**Returns:** `Customer` object
**Raises:**
- `InvalidTokenException` - No token or invalid token
- `InsufficientPermissionsException` - User is not customer (admin/vendor blocked)
**Usage:**
```python
current_customer: Customer = Depends(get_current_customer_api)
```
#### `get_current_user()`
**Purpose:** Authenticate any user (no role checking)
**Accepts:** Authorization header ONLY
**Returns:** `User` object (any role)
**Raises:**
- `InvalidTokenException` - No token or invalid token
**Usage:**
```python
current_user: User = Depends(get_current_user)
```
### Login Response Format
All login endpoints return:
```python
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"user": {
"id": 1,
"username": "admin",
"email": "admin@example.com",
"role": "admin",
"is_active": true
}
}
```
Additionally, the response sets an HTTP-only cookie:
- Admin: `admin_token` (path=/admin)
- Vendor: `vendor_token` (path=/vendor)
- Customer: `customer_token` (path=/shop)
---
## Security Model
### Role-Based Access Control Matrix
| User Role | Admin Portal | Vendor Portal | Shop Catalog | Customer Account |
|-----------|--------------|---------------|--------------|------------------|
| Admin | ✅ Full | ❌ Blocked | ✅ View | ❌ Blocked |
| Vendor | ❌ Blocked | ✅ Full | ✅ View | ❌ Blocked |
| Customer | ❌ Blocked | ❌ Blocked | ✅ View | ✅ Full |
| Anonymous | ❌ Blocked | ❌ Blocked | ✅ View | ❌ Blocked |
### Cookie Security Settings
All authentication cookies use the following security attributes:
```python
response.set_cookie(
key="<context>_token",
value=jwt_token,
httponly=True, # JavaScript cannot access (XSS protection)
secure=True, # HTTPS only in production
samesite="lax", # CSRF protection
max_age=3600, # Matches JWT expiry
path="/<context>" # Path restriction for isolation
)
```
### Token Validation
JWT tokens include:
- `sub` - User ID
- `role` - User role (admin/vendor/customer)
- `exp` - Expiration timestamp
- `iat` - Issued at timestamp
Tokens are validated on every request:
1. Extract token from cookie or header
2. Verify JWT signature
3. Check expiration
4. Load user from database
5. Verify user is active
6. Check role matches route requirements
### HTTPS Requirement
**Production Environment:**
- All cookies have `secure=True`
- HTTPS required for all authenticated routes
- HTTP requests automatically redirect to HTTPS
**Development Environment:**
- Cookies have `secure=False` for local testing
- HTTP allowed (http://localhost:8000)
---
## Testing Guidelines
### Manual Testing with Browser
#### Test Admin Authentication
1. **Navigate to admin login:**
```
http://localhost:8000/admin/login
```
2. **Login with admin credentials:**
- Username: `admin`
- Password: `admin123` (or your configured admin password)
3. **Verify cookie in DevTools:**
- Open DevTools → Application → Cookies
- Look for `admin_token` cookie
- Verify `Path` is `/admin`
- Verify `HttpOnly` is checked
- Verify `SameSite` is `Lax`
4. **Test navigation:**
- Navigate to `/admin/dashboard` - Should work ✅
- Navigate to `/vendor/TESTVENDOR/dashboard` - Should fail (cookie not sent) ❌
- Navigate to `/shop/account/dashboard` - Should fail (cookie not sent) ❌
5. **Logout:**
```
POST /api/v1/admin/auth/logout
```
#### Test Vendor Authentication
1. **Navigate to vendor login:**
```
http://localhost:8000/vendor/{VENDOR_CODE}/login
```
2. **Login with vendor credentials**
3. **Verify cookie in DevTools:**
- Look for `vendor_token` cookie
- Verify `Path` is `/vendor`
4. **Test navigation:**
- Navigate to `/vendor/{VENDOR_CODE}/dashboard` - Should work ✅
- Navigate to `/admin/dashboard` - Should fail ❌
- Navigate to `/shop/account/dashboard` - Should fail ❌
#### Test Customer Authentication
1. **Navigate to customer login:**
```
http://localhost:8000/shop/account/login
```
2. **Login with customer credentials**
3. **Verify cookie in DevTools:**
- Look for `customer_token` cookie
- Verify `Path` is `/shop`
4. **Test navigation:**
- Navigate to `/shop/account/dashboard` - Should work ✅
- Navigate to `/admin/dashboard` - Should fail ❌
- Navigate to `/vendor/{CODE}/dashboard` - Should fail ❌
### API Testing with curl
#### Test Admin API
```bash
# Login
curl -X POST http://localhost:8000/api/v1/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
# Save the access_token from response
# Test authenticated endpoint
curl http://localhost:8000/api/v1/admin/vendors \
-H "Authorization: Bearer <access_token>"
# Test cross-context blocking
curl http://localhost:8000/api/v1/vendor/TESTVENDOR/products \
-H "Authorization: Bearer <admin_access_token>"
# Should return 403 Forbidden
```
#### Test Vendor API
```bash
# Login
curl -X POST http://localhost:8000/api/v1/vendor/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"vendor","password":"vendor123"}'
# Test authenticated endpoint
curl http://localhost:8000/api/v1/vendor/TESTVENDOR/products \
-H "Authorization: Bearer <vendor_access_token>"
# Test cross-context blocking
curl http://localhost:8000/api/v1/admin/vendors \
-H "Authorization: Bearer <vendor_access_token>"
# Should return 403 Forbidden
```
#### Test Customer API
```bash
# Login
curl -X POST http://localhost:8000/api/v1/public/vendors/1/customers/login \
-H "Content-Type: application/json" \
-d '{"username":"customer","password":"customer123"}'
# Test authenticated endpoint with token
curl http://localhost:8000/api/v1/shop/orders \
-H "Authorization: Bearer <customer_access_token>"
# Test cross-context blocking
curl http://localhost:8000/api/v1/admin/vendors \
-H "Authorization: Bearer <customer_access_token>"
# Should return 403 Forbidden
```
### Frontend JavaScript Testing
#### Login and Store Token
```javascript
// Admin login
async function loginAdmin(username, password) {
const response = await fetch('/api/v1/admin/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
});
const data = await response.json();
// Cookie is set automatically
// Optionally store token for API calls
localStorage.setItem('admin_token', data.access_token);
// Redirect to dashboard
window.location.href = '/admin/dashboard';
}
```
#### Make API Call with Token
```javascript
// API call with token
async function fetchVendors() {
const token = localStorage.getItem('admin_token');
const response = await fetch('/api/v1/admin/vendors', {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.json();
}
```
#### Page Navigation (Cookie Automatic)
```javascript
// Just navigate - cookie sent automatically
window.location.href = '/admin/dashboard';
// Browser automatically includes admin_token cookie
```
### Automated Testing
#### Test Cookie Isolation
```python
import pytest
from fastapi.testclient import TestClient
def test_admin_cookie_not_sent_to_vendor_routes(client: TestClient):
# Login as admin
response = client.post('/api/v1/admin/auth/login', json={
'username': 'admin',
'password': 'admin123'
})
# Try to access vendor route (cookie should not be sent)
response = client.get('/vendor/TESTVENDOR/dashboard')
# Should redirect to login or return 401
assert response.status_code in [302, 401]
def test_vendor_token_blocked_from_admin_api(client: TestClient):
# Login as vendor
response = client.post('/api/v1/vendor/auth/login', json={
'username': 'vendor',
'password': 'vendor123'
})
vendor_token = response.json()['access_token']
# Try to access admin API with vendor token
response = client.get(
'/api/v1/admin/vendors',
headers={'Authorization': f'Bearer {vendor_token}'}
)
# Should return 403 Forbidden
assert response.status_code == 403
```
---
## Troubleshooting
### Common Issues
#### "Invalid token" error when navigating to pages
**Symptom:** User is logged in but gets "Invalid token" error
**Causes:**
- Token expired (default: 1 hour)
- Cookie was deleted
- Wrong cookie being sent
**Solution:**
- Check cookie expiration in DevTools
- Re-login to get fresh token
- Verify correct cookie exists with correct path
#### Cookie not being sent to endpoints
**Symptom:** API calls work with Authorization header but pages don't load
**Causes:**
- Cookie path mismatch
- Cookie expired
- Wrong domain
**Solution:**
- Verify cookie path matches route (e.g., `/admin` cookie for `/admin/*` routes)
- Check cookie expiration
- Ensure cookie domain matches current domain
#### "Admin cannot access vendor portal" error
**Symptom:** Admin user cannot access vendor routes
**Explanation:** This is intentional security design. Admins have their own portal at `/admin`. To manage vendors, use admin routes:
- View vendors: `/admin/vendors`
- Edit vendor: `/admin/vendors/{code}/edit`
Admins should not log into vendor portal as this violates security boundaries.
#### "Customer cannot access admin/vendor routes" error
**Symptom:** Customer trying to access management interfaces
**Explanation:** Customers only have access to:
- Public shop routes: `/shop/products`, etc.
- Their account: `/shop/account/*`
Admin and vendor portals are not accessible to customers.
#### Token works in Postman but not in browser
**Cause:** Postman uses Authorization header, browser uses cookies
**Solution:**
- For API testing: Use Authorization header
- For browser testing: Rely on cookies (automatic)
- For JavaScript API calls: Add Authorization header manually
### Debugging Tips
#### Check Cookie in Browser
```javascript
// In browser console
document.cookie.split(';').forEach(c => console.log(c.trim()));
```
#### Decode JWT Token
```javascript
// In browser console
function parseJwt(token) {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(atob(base64).split('').map(c => {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
}
const token = localStorage.getItem('admin_token');
console.log(parseJwt(token));
```
#### Check Server Logs
The authentication system logs all auth events:
```
INFO: Admin login successful: admin
INFO: Request: GET /admin/dashboard from 127.0.0.1
INFO: Response: 200 for GET /admin/dashboard (0.045s)
```
Look for:
- Login attempts
- Token validation errors
- Permission denials
---
## Best Practices
### For Developers
1. **Use the right dependency for the job:**
- HTML pages → `get_current_<context>_from_cookie_or_header`
- API endpoints → `get_current_<context>_api`
2. **Don't mix authentication contexts:**
- Admin users should use admin portal
- Vendor users should use vendor portal
- Customers should use shop
3. **Always check user.is_active:**
```python
if not current_user.is_active:
raise UserNotActiveException()
```
4. **Use type hints:**
```python
def my_route(current_user: User = Depends(get_current_admin_api)):
# IDE will have autocomplete for current_user
```
5. **Handle exceptions properly:**
```python
try:
# Your logic
except InvalidTokenException:
# Handle auth failure
except InsufficientPermissionsException:
# Handle permission denial
```
### For Frontend
1. **Store tokens securely:**
- Tokens in localStorage/sessionStorage are vulnerable to XSS
- Prefer using cookies for page navigation
- Only use localStorage for explicit API calls
2. **Always send Authorization header for API calls:**
```javascript
const token = localStorage.getItem('token');
fetch('/api/v1/admin/vendors', {
headers: { 'Authorization': `Bearer ${token}` }
});
```
3. **Handle 401/403 responses:**
```javascript
if (response.status === 401) {
// Redirect to login
window.location.href = '/admin/login';
}
```
4. **Clear tokens on logout:**
```javascript
localStorage.removeItem('token');
// Logout endpoint will clear cookie
await fetch('/api/v1/admin/auth/logout', { method: 'POST' });
```
### Security Considerations
1. **Never log tokens** - They're sensitive credentials
2. **Use HTTPS in production** - Required for secure cookies
3. **Set appropriate token expiration** - Balance security vs UX
4. **Rotate secrets regularly** - JWT signing keys
5. **Monitor failed auth attempts** - Detect brute force attacks
---
## Configuration
### Environment Variables
```bash
# JWT Configuration
JWT_SECRET_KEY=your-secret-key-here
JWT_ALGORITHM=HS256
JWT_EXPIRATION=3600 # 1 hour in seconds
# Environment
ENVIRONMENT=production # or development
# When ENVIRONMENT=production:
# - Cookies use secure=True (HTTPS only)
# - Debug mode is disabled
# - CORS is stricter
```
### Cookie Expiration
Cookies expire when:
1. JWT token expires (default: 1 hour)
2. User logs out (cookie deleted)
3. Browser session ends (for session cookies)
To change expiration:
```python
# In auth endpoint
response.set_cookie(
max_age=7200 # 2 hours
)
```
---
## AuthManager Class Reference
The `AuthManager` class handles all authentication and authorization operations including password hashing, JWT token management, and role-based access control.
::: middleware.auth.AuthManager
options:
show_source: false
heading_level: 3
show_root_heading: true
show_root_toc_entry: false
members:
- __init__
- hash_password
- verify_password
- authenticate_user
- create_access_token
- verify_token
- get_current_user
- require_role
- require_admin
- require_vendor
- require_customer
- create_default_admin_user
---
## Quick Reference
For a condensed cheat sheet of authentication patterns, see [Authentication Quick Reference](authentication-quick-reference.md).
---
## Related Documentation
- [RBAC System](RBAC.md) - Role-based access control and permissions
- [Architecture Overview](../architecture/auth-rbac.md) - System-wide authentication architecture
- [Backend Development](../backend/overview.md) - Backend development guide
- [API Reference](../backend/middleware-reference.md) - Auto-generated API documentation
---
**Document Version:** 1.0
**Last Updated:** November 2025
**Maintained By:** Backend Team