casbin-fastapi-decorator-casdoor
Casdoor OAuth2 authentication and Casbin authorization for casbin-fastapi-decorator.
Installation
pip install casbin-fastapi-decorator-casdoor
# or as an optional extra:
pip install "casbin-fastapi-decorator[casdoor]"
Quick start — facade
from fastapi import FastAPI
from casbin_fastapi_decorator_casdoor import CasdoorEnforceTarget, CasdoorIntegration
casdoor = CasdoorIntegration(
endpoint="http://localhost:8000",
client_id="...",
client_secret="...",
certificate=cert, # PEM string from Casdoor → Application → Cert
org_name="my_org",
application_name="my_app",
target=CasdoorEnforceTarget(
# enforce_id is resolved per-request from the user's JWT
enforce_id=lambda parsed: f"{parsed['owner']}/my_enforcer",
),
)
app = FastAPI()
app.include_router(casdoor.router) # GET /login, GET /callback, POST /logout
guard = casdoor.create_guard()
@app.get("/protected")
@guard.require_permission("resource", "read")
async def protected():
return {"ok": True}
CasdoorEnforceTarget
Selects which Casdoor API identifier to use for /api/enforce.
Exactly one field must be set — static string or a callable that receives
the parsed JWT payload.
from casbin_fastapi_decorator_casdoor import CasdoorEnforceTarget
# By enforcer (dynamic — org taken from the user's JWT)
CasdoorEnforceTarget(
enforce_id=lambda parsed: f"{parsed['owner']}/my_enforcer"
)
# By enforcer (static)
CasdoorEnforceTarget(enforce_id="my_org/my_enforcer")
# By permission object
CasdoorEnforceTarget(permission_id="my_org/can_edit_posts")
# By Casbin model
CasdoorEnforceTarget(model_id="my_org/rbac_model")
# By resource
CasdoorEnforceTarget(resource_id="my_org/articles_resource")
# By owner (all policies of the organisation)
CasdoorEnforceTarget(owner="my_org")
Manual composition
For advanced use cases — custom user_factory, multiple guards with
different targets, or fine-grained error handling — compose the building
blocks directly:
from casdoor import AsyncCasdoorSDK
from fastapi import HTTPException
from casbin_fastapi_decorator import PermissionGuard
from casbin_fastapi_decorator_casdoor import (
CasdoorEnforceTarget,
CasdoorEnforcerProvider,
CasdoorUserProvider,
make_casdoor_router,
)
sdk = AsyncCasdoorSDK(endpoint=..., client_id=..., ...)
# Custom user identity: use e-mail instead of "owner/name"
def email_factory(parsed: dict) -> str:
return parsed["email"]
target = CasdoorEnforceTarget(enforce_id="my_org/my_enforcer")
user_provider = CasdoorUserProvider(sdk=sdk)
enforcer_provider = CasdoorEnforcerProvider(
sdk=sdk,
target=target,
user_factory=email_factory,
)
router = make_casdoor_router(sdk=sdk, redirect_after_login="/docs")
guard = PermissionGuard(
user_provider=user_provider,
enforcer_provider=enforcer_provider,
error_factory=lambda user, *rv: HTTPException(403, "Forbidden"),
)
Components
CasdoorIntegration
Main facade. Accepts all Casdoor SDK parameters plus:
| Parameter | Default | Description |
|---|---|---|
target |
required | :class:CasdoorEnforceTarget — which Casdoor API identifier to use |
state_manager |
CookieStateManager() |
OAuth state issuance/verification strategy |
access_token_cookie |
"access_token" |
Cookie name for the access token |
refresh_token_cookie |
"refresh_token" |
Cookie name for the refresh token |
redirect_after_login |
"/" |
Path or absolute URL to redirect after OAuth2 callback. Relative ("/") stays on the same host; absolute ("https://app.example.com/") redirects to another host. |
cookie_secure |
True |
Set Secure flag on cookies |
cookie_httponly |
True |
Set HttpOnly flag on cookies |
cookie_samesite |
"lax" |
SameSite policy ("lax", "strict", "none") |
cookie_domain |
None |
Domain attribute. Use ".example.com" to share cookies across subdomains (e.g. *.my-site.ru) |
cookie_path |
"/" |
Path attribute of the cookie |
cookie_max_age |
None |
Max-Age in seconds; None = session cookie |
router_prefix |
"" |
URL prefix for /login, /callback and /logout |
CasdoorUserProvider
FastAPI dependency that validates both access_token and refresh_token
cookies via sdk.parse_jwt_token() and returns the raw access_token string.
Accepts optional unauthorized_error and invalid_token_error factories
for custom HTTP responses.
CasdoorEnforcerProvider
FastAPI dependency that returns a shared CasdoorEnforcer.
| Parameter | Default | Description |
|---|---|---|
sdk |
required | AsyncCasdoorSDK instance |
target |
required | :class:CasdoorEnforceTarget |
user_factory |
"{owner}/{name}" |
Callable (parsed_jwt) -> str |
make_casdoor_router
Factory that returns a fastapi.APIRouter with these endpoints:
GET {prefix}/login— issues OAuth2 state and redirects to CasdoorGET {prefix}/callback— validates state, exchanges OAuth2 code for tokens, sets cookiesPOST {prefix}/logout— calls Casdoor SSO logout (/api/sso-logout?logoutAll=true) when an access-token cookie is present, then clears authentication cookiesGET {prefix}/me— returns the current user's profile by parsing the JWT access token
Default state protection is provided by CookieStateManager:
- cookie name:
casdoor_oauth_state HttpOnly=True,Secure=True,SameSite=laxMax-Age=300
You can override state handling using CasdoorStateManager protocol
implementation (e.g. Redis/session-backed storage).
Metadata
Release files for casbin-fastapi-decorator-casdoor 1.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| casbin_fastapi_decorator_casdoor-1.3.1.tar.gz | 8.9 kB | Without provenance | Details for casbin_fastapi_decorator_casdoor-1.3.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| casbin_fastapi_decorator_casdoor-1.3.1-py3-none-any.whl | Python 3 | none | any | Details for casbin_fastapi_decorator_casdoor-1.3.1-py3-none-any.whl |
Total release size: 21.4 kB
Release files / casbin_fastapi_decorator_casdoor-1.3.1.tar.gz
| Download URL | casbin_fastapi_decorator_casdoor-1.3.1.tar.gz |
|---|---|
| Size | 8.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9ad7f90ba0ac30baa440b7391531cf148dd23d7786152bc6a461468af9019978
|
|
BLAKE2b-256 checksum How to use checksums |
6cf4fd020518592d49e5157a71384b3e7eaa74294363bb26bd6f197133db78f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / casbin_fastapi_decorator_casdoor-1.3.1-py3-none-any.whl
| Download URL | casbin_fastapi_decorator_casdoor-1.3.1-py3-none-any.whl |
|---|---|
| Size | 12.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ef1b046f5010fd2d04574a470e685957740cf19e55f6ef8c7784b0d57815677e
|
|
BLAKE2b-256 checksum How to use checksums |
74cbc37ccc378815ab684a3199c4d076906aab7b38d9c7382877c3e4f1b8038b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for casbin-fastapi-decorator-casdoor 1.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.