Comprehensive security system for authentication, authorization, and audit logging.
The security system provides:
- JWT-based Authentication: Secure token-based authentication
- RBAC (Role-Based Access Control): Fine-grained permission system
- OAuth/OpenID Connect: Support for Google, Microsoft, and Okta
- Audit Logging: Comprehensive tracking of all security-relevant actions
Register a new user account:
POST /auth/register
Content-Type: application/json
{
"username": "johndoe",
"email": "john@example.com",
"password": "securepassword123",
"full_name": "John Doe"
}Authenticate and receive JWT tokens:
POST /auth/login
Content-Type: application/json
{
"username": "johndoe",
"password": "securepassword123"
}Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"expires_in": 1800
}Include the access token in the Authorization header:
GET /api/projects
Authorization: Bearer <access_token>Refresh an expired access token:
POST /auth/refresh
Content-Type: application/json
{
"refresh_token": "<refresh_token>"
}Revoke refresh token:
POST /auth/logout
Content-Type: application/json
{
"refresh_token": "<refresh_token>"
}Authenticate with Google:
POST /auth/oauth/login
Content-Type: application/json
{
"provider": "google",
"access_token": "<google_access_token>"
}Authenticate with Microsoft:
POST /auth/oauth/login
Content-Type: application/json
{
"provider": "microsoft",
"access_token": "<microsoft_access_token>"
}Authenticate with Okta:
POST /auth/oauth/login
Content-Type: application/json
{
"provider": "okta",
"access_token": "<okta_access_token>",
"okta_domain": "dev-123456.okta.com"
}- admin: Full system access (all permissions)
- analyst: Can create projects, run analyses, view results
- viewer: Read-only access to projects and reports
projects:create- Create new projectsprojects:read- View projectsprojects:update- Update projectsprojects:delete- Delete projectsruns:create- Create analysis runsruns:read- View analysis runsruns:update- Update analysis runsruns:delete- Delete analysis runsreports:read- View reportsreports:export- Export reportsmodels:read- View model informationmodels:manage- Manage model registryusers:read- View user informationusers:manage- Manage users and rolesaudit:read- View audit logs
Protect routes with permission requirements:
from backend.src.security.rbac import require_permission
@router.post("/projects")
async def create_project(
project_data: ProjectCreate,
current_user: dict = Depends(require_permission("projects:create")),
):
# User has 'projects:create' permission
...Protect routes with role requirements:
from backend.src.security.rbac import require_role
@router.delete("/users/{user_id}")
async def delete_user(
user_id: str,
current_user: dict = Depends(require_role("admin")),
):
# User has 'admin' role
...from backend.src.security.rbac import RBACService
from backend.src.db.client import DatabaseClient
db = DatabaseClient(settings.postgres_dsn)
rbac = RBACService(db)
# Assign role to user
rbac.assign_role(user_id="...", role_name="analyst", assigned_by="admin_user_id")
# Grant permission to role
rbac.grant_permission(role_name="analyst", permission_name="projects:delete")
# Check user permissions
permissions = rbac.get_user_permissions(user_id="...")
has_permission = rbac.has_permission(user_id="...", permission="projects:create")All API requests are automatically logged with:
- User ID and username
- Action type (e.g., 'LOGIN', 'CREATE_PROJECT')
- Resource type and ID
- IP address and user agent
- Request method and path
- Response status
- Timestamp
Get audit logs (requires audit:read permission):
GET /audit/logs?user_id=<user_id>&action=LOGIN&limit=100
Authorization: Bearer <access_token>Query parameters:
user_id: Filter by user IDaction: Filter by action (e.g., 'LOGIN', 'CREATE_PROJECT')resource_type: Filter by resource type (e.g., 'project', 'run')resource_id: Filter by resource IDlimit: Maximum number of results (default: 100)offset: Offset for pagination (default: 0)
Log custom audit events:
from backend.src.security.audit import audit_log
audit_log(
action="CUSTOM_ACTION",
user_id=current_user["id"],
username=current_user["username"],
resource_type="project",
resource_id=project_id,
metadata={"custom_field": "value"},
)Security settings in base_settings.py or environment variables:
# JWT Configuration
JWT_SECRET_KEY=your-secret-key-here # CHANGE IN PRODUCTION!
JWT_ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=7
# Feature Flags
ENABLE_AUTHENTICATION=true
ENABLE_AUDIT_LOGGING=true
# OAuth Configuration (optional)
OAUTH_GOOGLE_CLIENT_ID=your-google-client-id
OAUTH_MICROSOFT_CLIENT_ID=your-microsoft-client-id
OAUTH_OKTA_DOMAIN=dev-123456.okta.comSecurity tables:
users: User accountsroles: User rolespermissions: Individual permissionsuser_roles: User-role assignmentsrole_permissions: Role-permission assignmentsrefresh_tokens: JWT refresh tokensaudit_logs: Audit log entries
See backend/src/db/schema.sql for full schema.
These endpoints don't require authentication:
/- Health check/docs- API documentation/openapi.json- OpenAPI schema/auth/login- User login/auth/register- User registration/auth/oauth/login- OAuth login/auth/refresh- Token refresh/metrics- Prometheus metrics
All other endpoints require authentication.
- Change JWT Secret: Set a strong
JWT_SECRET_KEYin production - Use HTTPS: Always use HTTPS in production
- Token Expiration: Access tokens expire in 30 minutes by default
- Refresh Tokens: Store refresh tokens securely (httpOnly cookies recommended)
- Password Policy: Enforce strong passwords (minimum 8 characters)
- Audit Logs: Regularly review audit logs for suspicious activity
- Role Management: Assign minimal necessary permissions
- OAuth: Configure OAuth providers with proper redirect URIs
- Ensure
Authorization: Bearer <token>header is present - Check that token hasn't expired
- Verify token is valid (not revoked)
- User doesn't have required permission
- Check user's roles and role permissions
- Superusers have all permissions automatically
- Verify access token is valid and not expired
- Check OAuth provider configuration
- Ensure correct provider name ('google', 'microsoft', 'okta')
- For Okta, provide
okta_domain