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>
274 lines
6.3 KiB
Markdown
274 lines
6.3 KiB
Markdown
# Authentication Quick Reference
|
|
|
|
**Version 1.0** | One-page reference for developers
|
|
|
|
---
|
|
|
|
## Function Cheat Sheet
|
|
|
|
### For HTML Pages (accept cookie OR header)
|
|
|
|
```python
|
|
from app.api.deps import (
|
|
get_current_admin_from_cookie_or_header,
|
|
get_current_store_from_cookie_or_header,
|
|
get_current_customer_from_cookie_or_header
|
|
)
|
|
from models.database.customer import Customer
|
|
|
|
# Admin page
|
|
@router.get("/admin/dashboard")
|
|
def admin_page(user: User = Depends(get_current_admin_from_cookie_or_header)):
|
|
pass
|
|
|
|
# Store page
|
|
@router.get("/store/{code}/dashboard")
|
|
def store_page(user: User = Depends(get_current_store_from_cookie_or_header)):
|
|
pass
|
|
|
|
# Customer page - NOTE: Returns Customer, not User!
|
|
@router.get("/storefront/account/dashboard")
|
|
def customer_page(customer: Customer = Depends(get_current_customer_from_cookie_or_header)):
|
|
pass # customer.id, customer.email, customer.store_id
|
|
```
|
|
|
|
### For API Endpoints (header only - better security)
|
|
|
|
```python
|
|
from app.api.deps import (
|
|
get_current_admin_api,
|
|
get_current_store_api,
|
|
get_current_customer_api
|
|
)
|
|
from models.database.customer import Customer
|
|
|
|
# Admin API
|
|
@router.post("/api/v1/admin/stores")
|
|
def admin_api(user: User = Depends(get_current_admin_api)):
|
|
pass
|
|
|
|
# Store API
|
|
@router.post("/api/v1/store/products")
|
|
def store_api(user: User = Depends(get_current_store_api)):
|
|
pass # user.token_store_id for store context
|
|
|
|
# Customer API - NOTE: Returns Customer, not User!
|
|
@router.post("/api/v1/storefront/orders")
|
|
def customer_api(request: Request, customer: Customer = Depends(get_current_customer_api)):
|
|
pass # customer.id, request.state.store validated to match
|
|
```
|
|
|
|
---
|
|
|
|
## Three Authentication Contexts
|
|
|
|
| Context | Cookie | Path | Role | Routes |
|
|
|---------|--------|------|------|--------|
|
|
| **Admin** | `admin_token` | `/admin` | `admin` | `/admin/*` |
|
|
| **Store** | `store_token` | `/store` | `store` | `/store/*` |
|
|
| **Customer** | `customer_token` | `/storefront` | `customer` | `/storefront/account/*` |
|
|
|
|
---
|
|
|
|
## Access Control Matrix
|
|
|
|
| User | Admin Portal | Store Portal | Shop Catalog | Customer Account |
|
|
|------|--------------|---------------|--------------|------------------|
|
|
| Admin | ✅ | ❌ | ✅ (view) | ❌ |
|
|
| Store | ❌ | ✅ | ✅ (view) | ❌ |
|
|
| Customer | ❌ | ❌ | ✅ (view) | ✅ |
|
|
| Anonymous | ❌ | ❌ | ✅ (view) | ❌ |
|
|
|
|
---
|
|
|
|
## Login Endpoints
|
|
|
|
```bash
|
|
# Admin
|
|
POST /api/v1/admin/auth/login
|
|
Body: {"username": "...", "password": "..."}
|
|
|
|
# Store
|
|
POST /api/v1/store/auth/login
|
|
Body: {"username": "...", "password": "..."}
|
|
|
|
# Customer
|
|
POST /api/v1/platform/stores/{store_id}/customers/login
|
|
Body: {"username": "...", "password": "..."}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"access_token": "eyJ0eXAi...",
|
|
"token_type": "Bearer",
|
|
"expires_in": 3600,
|
|
"user": {...}
|
|
}
|
|
```
|
|
|
|
Plus HTTP-only cookie is set automatically.
|
|
|
|
---
|
|
|
|
## Frontend Patterns
|
|
|
|
### Login (Store Token)
|
|
|
|
```javascript
|
|
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 set automatically
|
|
// Optionally store for API calls
|
|
localStorage.setItem('token', data.access_token);
|
|
|
|
// Navigate (cookie automatic)
|
|
window.location.href = '/admin/dashboard';
|
|
```
|
|
|
|
### API Call (Use Token)
|
|
|
|
```javascript
|
|
const token = localStorage.getItem('token');
|
|
|
|
const response = await fetch('/api/v1/admin/stores', {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
});
|
|
```
|
|
|
|
### Logout
|
|
|
|
```javascript
|
|
await fetch('/api/v1/admin/auth/logout', { method: 'POST' });
|
|
localStorage.removeItem('token');
|
|
window.location.href = '/admin/login';
|
|
```
|
|
|
|
---
|
|
|
|
## Testing Commands
|
|
|
|
### curl Examples
|
|
|
|
```bash
|
|
# Login
|
|
TOKEN=$(curl -X POST http://localhost:8000/api/v1/admin/auth/login \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"username":"admin","password":"admin123"}' \
|
|
| jq -r '.access_token')
|
|
|
|
# Authenticated request
|
|
curl http://localhost:8000/api/v1/admin/stores \
|
|
-H "Authorization: Bearer $TOKEN"
|
|
```
|
|
|
|
### Check Cookie in Browser
|
|
|
|
```javascript
|
|
// In DevTools console
|
|
document.cookie.split(';').forEach(c => console.log(c.trim()));
|
|
```
|
|
|
|
### Decode JWT
|
|
|
|
```javascript
|
|
function parseJwt(token) {
|
|
return JSON.parse(atob(token.split('.')[1]));
|
|
}
|
|
|
|
console.log(parseJwt(localStorage.getItem('token')));
|
|
```
|
|
|
|
---
|
|
|
|
## Common Errors
|
|
|
|
| Error | Meaning | Solution |
|
|
|-------|---------|----------|
|
|
| `INVALID_TOKEN` | No token or invalid | Re-login |
|
|
| `TOKEN_EXPIRED` | Token expired | Re-login |
|
|
| `ADMIN_REQUIRED` | Need admin role | Use correct account |
|
|
| `INSUFFICIENT_PERMISSIONS` | Wrong role for route | Use correct portal |
|
|
| `USER_NOT_ACTIVE` | Account disabled | Contact admin |
|
|
|
|
---
|
|
|
|
## Security Rules
|
|
|
|
1. ✅ **HTML pages** use `*_from_cookie_or_header` functions
|
|
2. ✅ **API endpoints** use `*_api` functions
|
|
3. ✅ **Admins** cannot access store/customer portals
|
|
4. ✅ **Stores** cannot access admin/customer portals
|
|
5. ✅ **Customers** cannot access admin/store portals
|
|
6. ✅ **Public storefront** (`/storefront/products`) needs no auth
|
|
7. ✅ **Customer accounts** (`/storefront/account/*`) need auth
|
|
|
|
---
|
|
|
|
## Cookie Security
|
|
|
|
All cookies have:
|
|
- ✅ `HttpOnly=true` - JavaScript cannot read (XSS protection)
|
|
- ✅ `Secure=true` - HTTPS only (production)
|
|
- ✅ `SameSite=Lax` - CSRF protection
|
|
- ✅ Path restriction - Context isolation
|
|
|
|
---
|
|
|
|
## Quick Debug
|
|
|
|
1. **Auth not working?**
|
|
- Check DevTools → Application → Cookies
|
|
- Verify cookie name and path match route
|
|
- Check token not expired
|
|
|
|
2. **Cross-context access denied?**
|
|
- This is intentional security
|
|
- Use correct portal for your role
|
|
|
|
3. **API call fails but page loads?**
|
|
- API needs `Authorization` header
|
|
- Page uses cookie (automatic)
|
|
- Add header to API calls
|
|
|
|
---
|
|
|
|
## File Locations
|
|
|
|
```
|
|
app/api/
|
|
├── deps.py # All auth functions here
|
|
├── v1/
|
|
├── admin/auth.py # Admin login
|
|
├── store/auth.py # Store login
|
|
└── public/stores/auth.py # Customer login
|
|
```
|
|
|
|
---
|
|
|
|
## Environment Variables
|
|
|
|
```bash
|
|
JWT_SECRET_KEY=your-secret-key
|
|
JWT_ALGORITHM=HS256
|
|
JWT_EXPIRATION=3600 # 1 hour
|
|
ENVIRONMENT=production
|
|
```
|
|
|
|
---
|
|
|
|
**Full Documentation:** See [Authentication System Documentation](authentication.md)
|
|
**Questions?** Contact backend team
|
|
|
|
---
|
|
|
|
**Print this page for quick reference!**
|