Skip to content

Guide: RBAC

Wire role_adapter, seed roles from config, set default_role, and protect routes with require_role / require_permission. This is the wiring the basic example omits.

Install

pip install "sreekarnv-fastauth[standard]"

main.py

from contextlib import asynccontextmanager
from fastapi import Depends, FastAPI
from fastauth import FastAuth, FastAuthConfig
from fastauth.adapters.sqlalchemy import SQLAlchemyAdapter
from fastauth.api.deps import require_auth, require_permission, require_role
from fastauth.providers.credentials import CredentialsProvider
from fastauth.types import UserData

adapter = SQLAlchemyAdapter(engine_url="sqlite+aiosqlite:///./auth.db")

config = FastAuthConfig(
    secret="change-me-in-production-min-32-bytes!!",
    providers=[CredentialsProvider()],
    adapter=adapter.user,
    token_adapter=adapter.token,
    roles=[
        {"name": "admin", "permissions": ["users:read", "users:write", "users:delete"]},
        {"name": "user",  "permissions": ["profile:read", "profile:write"]},
    ],
    default_role="user",
)

auth = FastAuth(config)
auth.role_adapter = adapter.role          # <-- required

@asynccontextmanager
async def lifespan(app: FastAPI):
    await adapter.create_tables()
    await auth.initialize_roles()          # <-- required to seed roles
    yield

app = FastAPI(lifespan=lifespan)
auth.mount(app)

@app.get("/dashboard")
async def dashboard(user: UserData = Depends(require_auth)):
    return {"hello": user["email"]}

@app.get("/admin")
async def admin_area(user: UserData = Depends(require_role("admin"))):
    return {"message": "Welcome, admin", "user_id": user["id"]}

@app.get("/reports")
async def reports(user: UserData = Depends(require_permission("users:read"))):
    return {"message": "Here are your reports", "user_id": user["id"]}

Bootstrap the first admin

A fresh DB has no admin role assigned. You have two options:

  • Via the admin endpoint, once someone is already admin — chicken-and-egg on a fresh DB.
  • Direct DB insert — insert a row into fastauth_user_roles for your user and "admin":
from sqlalchemy import insert
from fastauth.adapters.sqlalchemy.models import UserModel, user_roles, RoleModel

# inside an async session:
async with adapter._session_factory() as session:
    user = await session.scalar(select(UserModel).where(UserModel.email == "you@example.com"))
    await session.execute(insert(user_roles).values(user_id=user.id, role_name="admin"))
    await session.commit()

Try it

# Register — you get the default "user" role.
curl -X POST http://localhost:8000/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"a@b.com","password":"s3cur3-pw!"}'

# Inspect your roles:
curl http://localhost:8000/auth/roles/me -H "Authorization: Bearer $ACCESS"
# -> {"user_id":"...","roles":["user"],"permissions":["profile:read","profile:write"]}

# /reports needs "users:read" — fails for "user":
curl http://localhost:8000/auth/reports -H "Authorization: Bearer $ACCESS"
# -> 403 "Insufficient permissions"

Where to go next

  • RBAC feature — admin endpoints for managing roles at runtime.
  • Hooksmodify_jwt to embed roles/permissions into the token.