Skip to main content

Dead simple role-based access control for FastAPI

Project description

FastAPI Simple RBAC

Dead simple role-based access control for FastAPI.

Python 3.8+ FastAPI License: MIT

Why?

I got tired of writing the same role-checking boilerplate in every FastAPI project. This package lets you protect endpoints with a simple decorator:

@app.get("/admin")
@require_roles("admin")
def admin_only(request: Request):
    return {"message": "You're an admin!"}

That's it. No complex setup, no learning curve.

Installation

pip install fastapi-simple-rbac

Quick Start

from fastapi import FastAPI, Request
from fastapi_simple_rbac import RBACMiddleware, require_roles

app = FastAPI()
app.add_middleware(RBACMiddleware)

@app.get("/admin")
@require_roles("admin")
def admin_dashboard(request: Request):
    return {"message": "Welcome, admin!"}

By default, it looks for roles in JWT tokens (in the Authorization header). If you need something else, keep reading.

Examples

Multiple roles

# User needs BOTH roles
@require_roles(["admin", "editor"], require_all=True)
def admin_editor_only(request: Request):
    return {"message": "You're both admin AND editor"}

# User needs ANY of these roles  
@require_roles(["admin", "editor", "moderator"], require_all=False)
def staff_only(request: Request):
    return {"message": "You're staff"}

# Shorthand for the above
@require_any_role(["admin", "editor", "moderator"])
def staff_only_alt(request: Request):
    return {"message": "Same thing"}

Custom role sources

Don't use JWT? No problem. Write your own role getter:

def get_roles_from_database(request: Request):
    user_id = request.headers.get("X-User-ID")
    return database.get_user_roles(user_id)

app.add_middleware(RBACMiddleware, role_getter=get_roles_from_database)

Or from headers:

def get_roles_from_header(request: Request):
    roles = request.headers.get("X-User-Roles", "")
    return roles.split(",") if roles else []

app.add_middleware(RBACMiddleware, role_getter=get_roles_from_header)

Async role getters work too:

async def get_roles_from_api(request: Request):
    user_id = extract_user_id(request)
    async with httpx.AsyncClient() as client:
        response = await client.get(f"/users/{user_id}/roles")
        return response.json()["roles"]

app.add_middleware(RBACMiddleware, role_getter=get_roles_from_api)

JWT Configuration

app.add_middleware(
    RBACMiddleware,
    secret_key="your-secret-key",
    verify_jwt_signature=True,  # Set to False for development
    role_claim="permissions"    # Default is "roles"
)

Custom error messages

@require_roles("vip", error_message="VIP membership required!")
def vip_lounge(request: Request):
    return {"message": "Welcome to the VIP lounge"}

Custom error handling

def custom_error_handler(request: Request, exception: RBACException):
    return JSONResponse(
        status_code=exception.status_code,
        content={"error": "Nope", "details": exception.message}
    )

app.add_middleware(RBACMiddleware, error_handler=custom_error_handler)

FastAPI Dependencies

If you prefer dependency injection:

from fastapi import Depends
from fastapi_simple_rbac import get_current_user_roles, create_role_dependency

# Inject roles into your endpoint
@app.get("/profile")
def get_profile(roles: list = Depends(get_current_user_roles)):
    return {"your_roles": roles}

# Create reusable dependencies
admin_required = create_role_dependency("admin")

@app.get("/admin", dependencies=[Depends(admin_required)])
def admin_endpoint():
    return {"message": "Admin access"}

JWT Token Format

Your JWT should look like this:

{
  "sub": "user123",
  "roles": ["admin", "editor"],
  "exp": 1234567890
}

The roles can be a single string or an array. Both work fine.

Development

git clone https://github.com/yourusername/fastapi-simple-rbac
cd fastapi-simple-rbac
pip install -e ".[dev]"
pytest

License

MIT. Do whatever you want with it.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_simple_rbac-0.1.1.tar.gz (15.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_simple_rbac-0.1.1-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_simple_rbac-0.1.1.tar.gz.

File metadata

  • Download URL: fastapi_simple_rbac-0.1.1.tar.gz
  • Upload date:
  • Size: 15.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.1

File hashes

Hashes for fastapi_simple_rbac-0.1.1.tar.gz
Algorithm Hash digest
SHA256 0b0b99b6859cc4d3fd8bb8299894fa0105cab00d4b36729f27a1e397e02a00f9
MD5 50cfd488aca8abed5d2ec1f2c4ca4209
BLAKE2b-256 77d3c19a751efaaa6cf0394afbe723d0681afc723e86c49120cde514b77d6b55

See more details on using hashes here.

File details

Details for the file fastapi_simple_rbac-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_simple_rbac-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8bad3aa5bd6fbce8e8959f8a61643ee0600462ff45afc623248210c48354f6b3
MD5 aa0caac0fc7251a969d5135a7d4ae537
BLAKE2b-256 1c91ad781e74fd45b5df8f6a19babec5a87e75714bf55a20839a7b71bb151d3c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page