Skip to main content
Unlisted page
This page is unlisted. Search engines will not index it, and only users having a direct link can access it.

Auth & Security

info

Fluvius Framework provides built-in support for authentication and authorization using Casbin.

Authentication​

Basic Authentication​

Authenticate users:

from fluvius.fastapi.authentication import AuthMiddleware

app = FluviusFastAPI()
app.add_middleware(AuthMiddleware)

JWT Authentication​

Use JWT tokens:

from fluvius.fastapi.authentication import JWTAuth

auth = JWTAuth(secret_key="your-secret-key")

@app.post("/login")
async def login(username: str, password: str):
# Validate credentials
user = await validate_user(username, password)
token = auth.create_token(user.id)
return {"token": token}

API Key Authentication​

Use API keys:

from fluvius.fastapi.authentication import APIKeyAuth

auth = APIKeyAuth()

@app.post("/api/endpoint")
@auth.required
async def protected_endpoint():
# Requires API key
pass

Authorization with Casbin​

Casbin Integration​

Fluvius integrates with Casbin for policy-based access control:

from fluvius.casbin import CasbinEnforcer

enforcer = CasbinEnforcer(
model_path="path/to/model.conf",
policy_path="path/to/policy.csv"
)

Policy Model​

Define policy model:

# model.conf
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

Policy Rules​

Define policy rules:

# policy.csv
p, admin, user, create
p, admin, user, read
p, admin, user, update
p, admin, user, delete
p, user, user, read
p, user, user, update

Enforcing Policies​

Enforce policies in aggregates:

from fluvius.domain import Aggregate, action
from fluvius.casbin import require_permission

class UserAggregate(Aggregate):
@action(evt_key='user-created', resources=['user'])
@require_permission('user', 'create')
async def create_user(self, name: str, email: str):
# Only users with 'user:create' permission can call this
pass

Resource-Based Authorization​

Resource Authorization​

Authorize based on resources:

@action(evt_key='user-updated', resources=['user'])
@require_permission('user', 'update')
async def update_user(self, name: str):
# Requires 'user:update' permission
pass

Resource Ownership​

Check resource ownership:

@action(evt_key='user-updated', resources=['user'])
@require_permission('user', 'update')
async def update_user(self, name: str):
# Check if user owns the resource
if not self.domain.context.user_id == self._state.owner_id:
raise PermissionError("Not authorized")
pass

Role-Based Access Control (RBAC)​

Roles​

Define roles:

# Assign roles
enforcer.add_grouping_policy("alice", "admin")
enforcer.add_grouping_policy("bob", "user")

Role Permissions​

Define role permissions:

# Admin can do everything
enforcer.add_policy("admin", "user", "create")
enforcer.add_policy("admin", "user", "read")
enforcer.add_policy("admin", "user", "update")
enforcer.add_policy("admin", "user", "delete")

# User can only read and update
enforcer.add_policy("user", "user", "read")
enforcer.add_policy("user", "user", "update")

Attribute-Based Access Control (ABAC)​

Attributes​

Use attributes for authorization:

# Check attributes
enforcer.add_policy("admin", "user", "create", "department == 'IT'")

Dynamic Policies​

Create dynamic policies:

# Policy based on resource attributes
if resource.department == user.department:
enforcer.add_policy(user.id, resource.type, "read")

Security Best Practices​

1. Validate Input​

Always validate input:

from pydantic import BaseModel, EmailStr

class CreateUserRequest(BaseModel):
name: str
email: EmailStr # Validated email

@action(evt_key='user-created')
async def create_user(self, name: str, email: str):
# Input is validated by Pydantic
pass

2. Use HTTPS​

Always use HTTPS in production:

# Use HTTPS
app = FluviusFastAPI()
# Configure SSL certificates

3. Secure Secrets​

Store secrets securely:

import os

# Use environment variables
secret_key = os.getenv("SECRET_KEY")

# Never commit secrets
# Use .env file (gitignored)

4. Rate Limiting​

Implement rate limiting:

from slowapi import Limiter

limiter = Limiter(key_func=get_remote_address)

@app.post("/api/users")
@limiter.limit("10/minute")
async def create_user():
pass

5. Input Sanitization​

Sanitize user input:

import html

@action(evt_key='user-created')
async def create_user(self, name: str, email: str):
# Sanitize input
name = html.escape(name)
email = html.escape(email)
pass

Security Headers​

CORS Configuration​

Configure CORS:

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
CORSMiddleware,
allow_origins=["https://example.com"],
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["*"],
)

Security Headers​

Add security headers:

@app.middleware("http")
async def add_security_headers(request, call_next):
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-XSS-Protection"] = "1; mode=block"
return response

Audit Logging​

Audit Events​

Log security events:

@action(evt_key='user-created')
async def create_user(self, name: str, email: str):
# Event is automatically logged
# Include audit information
logger.info(f"User created by {self.domain.context.user_id}")
pass

Access Logging​

Log access attempts:

@middleware
async def access_logging_middleware(request, call_next):
logger.info(f"Access: {request.method} {request.url} by {request.user}")
response = await call_next(request)
return response

Next Steps​