Generate Documentation
It feels incomplete if there is no documentation because fastapi-jwt-auth that uses starlette request and response directly to get headers or cookies, you must manually generate the documentation. Thanks to FastAPI
you can generate doc easily via Extending OpenAPI
.
Here is an example to generate the doc:
from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.openapi.utils import get_openapi
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from async_fastapi_jwt_auth import AuthJWT
from async_fastapi_jwt_auth.exceptions import AuthJWTException
from async_fastapi_jwt_auth.auth_jwt import AuthJWTBearer
app = FastAPI()
auth_dep = AuthJWTBearer()
class User(BaseModel):
username: str
password: str
class Settings(BaseModel):
authjwt_secret_key: str = "secret"
@AuthJWT.load_config
def get_config():
return Settings()
@app.exception_handler(AuthJWTException)
def authjwt_exception_handler(request: Request, exc: AuthJWTException):
return JSONResponse(status_code=exc.status_code, content={"detail": exc.message})
@app.post("/login")
async def login(user: User, authorize: AuthJWT = Depends(auth_dep)):
if user.username != "test" or user.password != "test":
raise HTTPException(status_code=401, detail="Bad username or password")
access_token = await authorize.create_access_token(subject=user.username)
return {"access_token": access_token}
@app.get("/protected", operation_id="authorize")
async def protected(authorize: AuthJWT = Depends(auth_dep)):
await authorize.jwt_required()
current_user = await authorize.get_jwt_subject()
return {"user": current_user}
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Custom title",
version="2.5.0",
description="This is a very custom OpenAPI schema",
routes=app.routes,
)
# Custom documentation async-fastapi-jwt-auth
headers = {
"name": "Authorization",
"in": "header",
"required": True,
"schema": {"title": "Authorization", "type": "string"},
}
# Get routes from index 4 because before that fastapi define router for /openapi.json, /redoc, /docs, etc
# Get all router where operation_id is "authorize"
router_authorize = [
route for route in app.routes[4:] if route.operation_id == "authorize"
]
for route in router_authorize:
method = list(route.methods)[0].lower()
try:
# If the router has another parameter
openapi_schema["paths"][route.path][method]["parameters"].append(headers)
except Exception:
# If the router doesn't have a parameter
openapi_schema["paths"][route.path][method].update(
{"parameters": [headers]}
)
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi