revamping documentation
This commit is contained in:
522
docs/architecture/auth-rbac.md
Normal file
522
docs/architecture/auth-rbac.md
Normal file
@@ -0,0 +1,522 @@
|
||||
# Authentication & Role-Based Access Control (RBAC)
|
||||
|
||||
Complete guide to the authentication and authorization system powering the multi-tenant platform.
|
||||
|
||||
## Overview
|
||||
|
||||
The platform uses a JWT-based authentication system combined with role-based access control (RBAC) to secure all interfaces:
|
||||
- **Admin** interface
|
||||
- **Vendor** dashboard
|
||||
- **Shop** storefront
|
||||
- **REST API** endpoints
|
||||
|
||||
## Authentication System
|
||||
|
||||
### Technology Stack
|
||||
|
||||
- **JWT (JSON Web Tokens)**: Stateless authentication
|
||||
- **bcrypt**: Secure password hashing
|
||||
- **Jose**: JWT encoding/decoding library
|
||||
- **FastAPI Security**: OAuth2 password bearer flow
|
||||
|
||||
### Authentication Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant API
|
||||
participant AuthManager
|
||||
participant Database
|
||||
|
||||
Client->>API: POST /api/v1/auth/login<br/>{username, password}
|
||||
API->>AuthManager: authenticate_user()
|
||||
AuthManager->>Database: Query user by username/email
|
||||
Database-->>AuthManager: User record
|
||||
AuthManager->>AuthManager: verify_password()
|
||||
AuthManager-->>API: User object
|
||||
API->>AuthManager: create_access_token()
|
||||
AuthManager-->>API: JWT token
|
||||
API-->>Client: {access_token, token_type, expires_in}
|
||||
|
||||
Note over Client: Store token
|
||||
|
||||
Client->>API: GET /api/v1/resource<br/>Authorization: Bearer <token>
|
||||
API->>AuthManager: verify_token()
|
||||
AuthManager->>AuthManager: Decode JWT
|
||||
AuthManager->>Database: Query user by ID
|
||||
Database-->>AuthManager: User object
|
||||
AuthManager-->>API: Current user
|
||||
API->>API: Process request
|
||||
API-->>Client: Resource data
|
||||
```
|
||||
|
||||
## User Roles
|
||||
|
||||
The platform has three distinct user roles, each with specific permissions and access levels:
|
||||
|
||||
### Customer Role
|
||||
|
||||
**Access**: Public shop and own account space
|
||||
|
||||
**Capabilities**:
|
||||
- Browse vendor shops
|
||||
- Place orders
|
||||
- Manage their own account and order history
|
||||
- View order status
|
||||
- Update profile information
|
||||
- Can register directly from shop frontend
|
||||
|
||||
**Account Creation**: Self-registration via shop frontend (email verification required)
|
||||
|
||||
**Authentication**: Standard JWT authentication
|
||||
|
||||
### Vendor Role
|
||||
|
||||
**Access**: Vendor area based on permissions
|
||||
|
||||
**Types**:
|
||||
- **Vendor Owner**: Full access to vendor dashboard and settings
|
||||
- **Vendor Team Members**: Access based on assigned permissions
|
||||
|
||||
**Capabilities**:
|
||||
- Manage products and inventory
|
||||
- Process orders
|
||||
- View analytics and reports
|
||||
- Configure shop settings (owners only)
|
||||
- Manage team members (owners only)
|
||||
- Access vendor-specific APIs
|
||||
|
||||
**Account Creation**:
|
||||
- Owners: Created automatically when admin creates a vendor
|
||||
- Team members: Invited by vendor owner via email
|
||||
|
||||
**Permissions System**: Team members can have granular permissions for different areas
|
||||
|
||||
### Admin Role
|
||||
|
||||
**Access**: Full platform administration
|
||||
|
||||
**Capabilities**:
|
||||
- Manage all vendors
|
||||
- Create/manage vendor accounts
|
||||
- Access system settings
|
||||
- View all data across the platform
|
||||
- Manage users of all types
|
||||
- Access audit logs
|
||||
- Platform-wide analytics
|
||||
|
||||
**Account Creation**: Created by super admins on the backend
|
||||
|
||||
**Super Privileges**: Admins can access all areas including vendor and customer sections
|
||||
|
||||
## Application Areas & Access Control
|
||||
|
||||
The platform has three distinct areas with different access requirements:
|
||||
|
||||
| Area | URL Pattern | Access | Purpose |
|
||||
|------|-------------|--------|---------|
|
||||
| **Admin** | `/admin/*` or `admin.platform.com` | Admin users only | Platform administration and vendor management |
|
||||
| **Vendor** | `/vendor/*` | Vendor owners and team members | Vendor dashboard and shop management |
|
||||
| **Shop** | `/shop/*`, custom domains, subdomains | Customers and public | Public-facing eCommerce storefront |
|
||||
| **API** | `/api/*` | All authenticated users (role-based) | REST API for all operations |
|
||||
|
||||
## Account Registration Flow
|
||||
|
||||
### Admin Accounts
|
||||
- ❌ Cannot register from frontend
|
||||
- ✅ Created by super admins on the backend
|
||||
- Used for: Platform administration
|
||||
|
||||
### Vendor Accounts
|
||||
- ❌ Cannot register from frontend
|
||||
- ✅ **Vendor Owners**: Automatically created when admin creates a new vendor
|
||||
- ✅ **Team Members**: Invited by vendor owner via email invitation
|
||||
- Activation: Upon clicking email verification link
|
||||
|
||||
### Customer Accounts
|
||||
- ✅ Can register directly on vendor shop
|
||||
- Activation: Upon clicking registration email link
|
||||
- Used for: Shopping and order management
|
||||
|
||||
## Role Enforcement Methods
|
||||
|
||||
The `AuthManager` class provides several methods for role-based access control:
|
||||
|
||||
### require_admin()
|
||||
|
||||
Restricts access to admin users only.
|
||||
|
||||
**Usage**:
|
||||
```python
|
||||
from fastapi import Depends
|
||||
from models.database.user import User
|
||||
from middleware.auth import auth_manager
|
||||
|
||||
@app.get("/admin/dashboard")
|
||||
async def admin_dashboard(
|
||||
current_user: User = Depends(auth_manager.require_admin)
|
||||
):
|
||||
return {"message": "Admin access"}
|
||||
```
|
||||
|
||||
**Raises**: `AdminRequiredException` if user is not admin
|
||||
|
||||
### require_vendor()
|
||||
|
||||
Allows access to vendor users and admins.
|
||||
|
||||
**Usage**:
|
||||
```python
|
||||
@app.get("/vendor/products")
|
||||
async def vendor_products(
|
||||
current_user: User = Depends(auth_manager.require_vendor)
|
||||
):
|
||||
return {"products": [...]}
|
||||
```
|
||||
|
||||
**Raises**: `InsufficientPermissionsException` if user is not vendor or admin
|
||||
|
||||
### require_customer()
|
||||
|
||||
Allows access to customer users and admins.
|
||||
|
||||
**Usage**:
|
||||
```python
|
||||
@app.get("/shop/orders")
|
||||
async def customer_orders(
|
||||
current_user: User = Depends(auth_manager.require_customer)
|
||||
):
|
||||
return {"orders": [...]}
|
||||
```
|
||||
|
||||
**Raises**: `InsufficientPermissionsException` if user is not customer or admin
|
||||
|
||||
### require_role()
|
||||
|
||||
Custom role enforcement for specific roles.
|
||||
|
||||
**Usage**:
|
||||
```python
|
||||
@app.get("/custom-endpoint")
|
||||
@auth_manager.require_role("custom_role")
|
||||
async def custom_endpoint(current_user: User):
|
||||
return {"message": "Custom role access"}
|
||||
```
|
||||
|
||||
**Returns**: Decorator function that validates role
|
||||
|
||||
## JWT Token Structure
|
||||
|
||||
### Token Payload
|
||||
|
||||
```json
|
||||
{
|
||||
"sub": "123", // User ID (JWT standard claim)
|
||||
"username": "testuser", // Username for display
|
||||
"email": "user@example.com", // User email
|
||||
"role": "vendor", // User role
|
||||
"exp": 1700000000, // Expiration timestamp (JWT standard)
|
||||
"iat": 1699999000 // Issued at timestamp (JWT standard)
|
||||
}
|
||||
```
|
||||
|
||||
### Token Configuration
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `JWT_SECRET_KEY` | Secret key for JWT signing | Development key (change in production!) |
|
||||
| `JWT_EXPIRE_MINUTES` | Token expiration time in minutes | 30 |
|
||||
|
||||
**Environment Configuration**:
|
||||
```bash
|
||||
# .env
|
||||
JWT_SECRET_KEY=your-super-secret-key-change-in-production
|
||||
JWT_EXPIRE_MINUTES=30
|
||||
```
|
||||
|
||||
## Permission Hierarchy
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Admin] --> B[Full Platform Access]
|
||||
A --> C[Can Access All Areas]
|
||||
|
||||
D[Vendor Owner] --> E[Vendor Dashboard]
|
||||
D --> F[Team Management]
|
||||
D --> G[Shop Settings]
|
||||
D --> H[All Vendor Data]
|
||||
|
||||
I[Vendor Team Member] --> E
|
||||
I --> J[Limited Based on Permissions]
|
||||
|
||||
K[Customer] --> L[Shop Access]
|
||||
K --> M[Own Orders]
|
||||
K --> N[Own Profile]
|
||||
```
|
||||
|
||||
**Admin Override**: Admin users have implicit access to all areas, including vendor and customer sections. This allows admins to provide support and manage the platform effectively.
|
||||
|
||||
## Security Features
|
||||
|
||||
### Password Security
|
||||
|
||||
**Hashing**:
|
||||
- Algorithm: bcrypt
|
||||
- Automatic salt generation
|
||||
- Configurable work factor
|
||||
|
||||
**Example**:
|
||||
```python
|
||||
from middleware.auth import auth_manager
|
||||
|
||||
# Hash password
|
||||
hashed = auth_manager.hash_password("user_password")
|
||||
|
||||
# Verify password
|
||||
is_valid = auth_manager.verify_password("user_password", hashed)
|
||||
```
|
||||
|
||||
### Token Security
|
||||
|
||||
**Features**:
|
||||
- Signed with secret key (prevents tampering)
|
||||
- Includes expiration time
|
||||
- Stateless (no server-side session storage)
|
||||
- Short-lived (30 minutes default)
|
||||
|
||||
**Best Practices**:
|
||||
- Use HTTPS in production
|
||||
- Store tokens securely on client
|
||||
- Implement token refresh mechanism
|
||||
- Clear tokens on logout
|
||||
|
||||
### Protection Against Common Attacks
|
||||
|
||||
**SQL Injection**:
|
||||
- ✅ SQLAlchemy ORM with parameterized queries
|
||||
- ✅ Input validation with Pydantic
|
||||
|
||||
**XSS (Cross-Site Scripting)**:
|
||||
- ✅ Jinja2 auto-escaping
|
||||
- ✅ Content Security Policy headers
|
||||
|
||||
**CSRF (Cross-Site Request Forgery)**:
|
||||
- ✅ JWT tokens in Authorization header (not cookies)
|
||||
- ✅ SameSite cookie attribute for session cookies
|
||||
|
||||
**Brute Force**:
|
||||
- ✅ Rate limiting on auth endpoints
|
||||
- ✅ Account lockout after failed attempts (future)
|
||||
|
||||
## Authentication Endpoints
|
||||
|
||||
### Register User
|
||||
|
||||
```http
|
||||
POST /api/v1/auth/register
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"username": "testuser",
|
||||
"password": "securepassword123"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"id": 123,
|
||||
"username": "testuser",
|
||||
"email": "user@example.com",
|
||||
"role": "customer",
|
||||
"is_active": true
|
||||
}
|
||||
```
|
||||
|
||||
### Login
|
||||
|
||||
```http
|
||||
POST /api/v1/auth/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "testuser",
|
||||
"password": "securepassword123"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
|
||||
"token_type": "bearer",
|
||||
"expires_in": 1800
|
||||
}
|
||||
```
|
||||
|
||||
### Using Authentication
|
||||
|
||||
Include the JWT token in the Authorization header:
|
||||
|
||||
```http
|
||||
GET /api/v1/resource
|
||||
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Authentication Errors
|
||||
|
||||
| Error | Status Code | Description |
|
||||
|-------|-------------|-------------|
|
||||
| `InvalidCredentialsException` | 401 | Username/password incorrect |
|
||||
| `InvalidTokenException` | 401 | JWT token invalid or malformed |
|
||||
| `TokenExpiredException` | 401 | JWT token has expired |
|
||||
| `UserNotActiveException` | 403 | User account is inactive |
|
||||
|
||||
### Authorization Errors
|
||||
|
||||
| Error | Status Code | Description |
|
||||
|-------|-------------|-------------|
|
||||
| `AdminRequiredException` | 403 | Endpoint requires admin role |
|
||||
| `InsufficientPermissionsException` | 403 | User lacks required permissions |
|
||||
|
||||
## Testing Authentication
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```python
|
||||
import pytest
|
||||
from middleware.auth import AuthManager
|
||||
|
||||
def test_password_hashing():
|
||||
auth_manager = AuthManager()
|
||||
|
||||
password = "test_password"
|
||||
hashed = auth_manager.hash_password(password)
|
||||
|
||||
assert auth_manager.verify_password(password, hashed)
|
||||
assert not auth_manager.verify_password("wrong_password", hashed)
|
||||
|
||||
def test_create_token():
|
||||
auth_manager = AuthManager()
|
||||
user = create_test_user(role="vendor")
|
||||
|
||||
token_data = auth_manager.create_access_token(user)
|
||||
|
||||
assert "access_token" in token_data
|
||||
assert "token_type" in token_data
|
||||
assert token_data["token_type"] == "bearer"
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
```python
|
||||
def test_login_flow(client):
|
||||
# Register user
|
||||
response = client.post("/api/v1/auth/register", json={
|
||||
"username": "testuser",
|
||||
"email": "test@example.com",
|
||||
"password": "password123"
|
||||
})
|
||||
assert response.status_code == 200
|
||||
|
||||
# Login
|
||||
response = client.post("/api/v1/auth/login", json={
|
||||
"username": "testuser",
|
||||
"password": "password123"
|
||||
})
|
||||
assert response.status_code == 200
|
||||
token = response.json()["access_token"]
|
||||
|
||||
# Access protected endpoint
|
||||
response = client.get(
|
||||
"/api/v1/profile",
|
||||
headers={"Authorization": f"Bearer {token}"}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### For Developers
|
||||
|
||||
1. **Always hash passwords**: Never store plain text passwords
|
||||
2. **Use dependency injection**: Leverage FastAPI's `Depends` for auth
|
||||
3. **Validate tokens**: Always validate tokens on protected endpoints
|
||||
4. **Check permissions**: Verify user has required role/permissions
|
||||
5. **Log auth events**: Track login, logout, failed attempts
|
||||
|
||||
### For Operations
|
||||
|
||||
1. **Strong secret keys**: Use long, random JWT secret keys
|
||||
2. **HTTPS only**: Never send tokens over HTTP
|
||||
3. **Token expiration**: Keep token lifetimes short
|
||||
4. **Rotate secrets**: Periodically rotate JWT secret keys
|
||||
5. **Monitor auth logs**: Watch for suspicious activity
|
||||
|
||||
### For Security
|
||||
|
||||
1. **Rate limiting**: Limit auth endpoint requests
|
||||
2. **Account lockout**: Implement after N failed attempts
|
||||
3. **Email verification**: Require email confirmation
|
||||
4. **Password policies**: Enforce strong password requirements
|
||||
5. **2FA support**: Consider adding two-factor authentication
|
||||
|
||||
## Examples
|
||||
|
||||
### Protecting an Endpoint
|
||||
|
||||
```python
|
||||
from fastapi import Depends, APIRouter
|
||||
from sqlalchemy.orm import Session
|
||||
from middleware.auth import auth_manager
|
||||
from app.core.database import get_db
|
||||
from models.database.user import User
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/vendors")
|
||||
async def get_vendors(
|
||||
current_user: User = Depends(auth_manager.require_admin),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Only admins can list all vendors."""
|
||||
vendors = db.query(Vendor).all()
|
||||
return {"vendors": vendors}
|
||||
```
|
||||
|
||||
### Multi-Role Access
|
||||
|
||||
```python
|
||||
@router.get("/dashboard")
|
||||
async def dashboard(
|
||||
current_user: User = Depends(auth_manager.get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Accessible by all authenticated users, but returns different data."""
|
||||
if current_user.role == "admin":
|
||||
# Admin sees everything
|
||||
data = get_admin_dashboard(db)
|
||||
elif current_user.role == "vendor":
|
||||
# Vendor sees their data only
|
||||
data = get_vendor_dashboard(db, current_user.id)
|
||||
else:
|
||||
# Customer sees their orders
|
||||
data = get_customer_dashboard(db, current_user.id)
|
||||
|
||||
return data
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Middleware Stack](middleware.md) - System-wide request processing
|
||||
- [Error Handling](../api/error-handling.md) - Exception handling
|
||||
- [Backend API Reference](../backend/middleware-reference.md) - Technical AuthManager docs
|
||||
- [Testing Guide](../testing/testing-guide.md) - Testing authentication
|
||||
|
||||
## Technical Reference
|
||||
|
||||
For detailed API documentation of authentication classes and methods:
|
||||
- [AuthManager API Reference](../backend/middleware-reference.md#authentication-authorization)
|
||||
Reference in New Issue
Block a user