Cookie
JWTUserProvider can also extract tokens from cookies. This is useful for browser-based applications where tokens are stored in HTTP-only cookies.
Setup
Pass cookie_name to enable cookie extraction:
from casbin_fastapi_decorator_jwt import JWTUserProvider
from pydantic import BaseModel
class User(BaseModel):
role: str
user_provider = JWTUserProvider(
secret_key="your-secret-key",
algorithm="HS256",
user_model=User,
cookie_name="access_token", # reads from this cookie
)
Behavior
When cookie_name is set, the provider checks both the Bearer header and the cookie. The exact priority depends on the provider's implementation — typically the header takes precedence if both are present.
Full example
import jwt
import casbin
from fastapi import FastAPI, HTTPException, Response
from casbin_fastapi_decorator import PermissionGuard
from casbin_fastapi_decorator_jwt import JWTUserProvider
from pydantic import BaseModel
app = FastAPI()
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
class User(BaseModel):
role: str
user_provider = JWTUserProvider(
secret_key=SECRET_KEY,
algorithm=ALGORITHM,
user_model=User,
cookie_name="access_token",
)
async def get_enforcer() -> casbin.Enforcer:
return casbin.Enforcer("casbin/model.conf", "casbin/policy.csv")
guard = PermissionGuard(
user_provider=user_provider,
enforcer_provider=get_enforcer,
error_factory=lambda *_: HTTPException(403, "Forbidden"),
)
@app.post("/login")
async def login(role: str, response: Response) -> dict:
"""Generate a JWT token and set it as a cookie."""
token = jwt.encode({"role": role}, SECRET_KEY, algorithm=ALGORITHM)
response.set_cookie(
key="access_token",
value=token,
httponly=True,
samesite="strict",
)
return {"message": "Logged in"}
@app.get("/posts")
@guard.require_permission("post", "read")
async def list_posts() -> list[dict]:
return [{"id": 1, "title": "Hello"}]
Testing with cookies
# Login and save cookies
curl -c cookies.txt -X POST "http://localhost:8000/login?role=editor"
# Use the cookie
curl -b cookies.txt http://localhost:8000/posts
Security recommendations
- Always use
httponly=Trueto prevent JavaScript access - Use
samesite="strict"orsamesite="lax"to mitigate CSRF - Use
secure=Truein production (requires HTTPS)
response.set_cookie(
key="access_token",
value=token,
httponly=True,
secure=True, # HTTPS only
samesite="strict",
max_age=3600, # 1 hour
)