1

Basic goal: A means of authenticating most (but not all) routes in one place (a separate file), seamlessly so that I don't have to add code/documentation to every one of the routes in order to get auth or openapi to work.

I would like to implement a basic Bearer Authorization in FastAPI, but do so in class-based middleware. I've done this successfully, but I have not seen how to do this in a way that OpenAPI is aware of it (i.e., there's no way to set auth tokens in the docs).

class AuthMiddleware:
    def __init__(self, settings):
        self.settings = settings

    async def __call__(self, request: Request, call_next):
        if self.is_protected_url(request.method, request.url.path):
            auth = request.headers.get("Authorization")
            scheme, data = (auth or " ").split(" ", 1)
            if scheme != "Bearer":
                return JSONResponse(None, 401, {"WWW-Authenticate": "Bearer"})
            if data != self.settings.auth_token:
                return JSONResponse(None, 401, {"WWW-Authenticate": "Bearer"})

        return await call_next(request)

    def is_protected_url(self, method, url):
        """ does what it does """

In the main file:

from path.to.auth import AuthMiddleware

auth_middleware = AuthMiddleware(settings)
app.middleware("http")(auth_middleware)

There seems to be some existing auth classes to use, but I can't figure out how to properly get them to work in a class-based Middleware that is in a separate file (Depends doesn't resolve).

See

2
  • this might help medium.com/@chandanp20k/… Commented Dec 16, 2024 at 19:38
  • Have two APIRouters on the root level - one for authenticated routes and one for those without. Import OAuth2PasswordBearer - from fastapi.security import OAuth2PasswordBearer, and add it as a default dependency to the API router that handles your routes that require authentication. Add any routes (or other routers) under that specific router. FastAPI's built-in openapi generator will know about this class and add the proper information (and send authentication) when you use that class. See fastapi.tiangolo.com/tutorial/security/simple-oauth2/… Commented Dec 16, 2024 at 22:40

1 Answer 1

0

You can use a global dependency: https://fastapi.tiangolo.com/tutorial/dependencies/global-dependencies/

from fastapi import Depends, FastAPI, Request
from fastapi.openapi.utils import get_openapi

async def verify_token(request: Request):
    # verify token code
    pass

app = FastAPI(
    title="<title>",
    description="<desc>",
    version="<version>",
    dependencies=[Depends(verify_token)]
)

def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    openapi_schema = get_openapi(
        title="<title>",
        description="<desc>",
        version="<version>",
        routes=app.routes,
    )
    openapi_schema["components"]["securitySchemes"] = {
        "BearerAuth": {
            "type": "http",
            "scheme": "bearer",
            "bearerFormat": "sso-jwt",
        }
    }
    openapi_schema["security"] = [{"BearerAuth": []}]
    app.openapi_schema = openapi_schema
    return app.openapi_schema

app.openapi = custom_openapi

Make sure to configure bearerFormat for your usage.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.