I'm sending an id_token
in my cookies to a FastAPI application that also has a mounted Starlette app. I have a CustomMiddleware
class that I'd like to run before the AuthenticationMiddleware
for token validation. However, the AuthenticationMiddleware
always runs first:
import uvicorn
from fastapi import FastAPI
from starlette.applications import Starlette
from starlette.authentication import (
AuthCredentials,
AuthenticationBackend,
BaseUser,
)
from starlette.middleware import Middleware
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
from starlette.routing import Route
class AuthenticatedUser(BaseUser):
def __init__(self, display_name: str) -> None:
self._display_name = display_name
@property
def is_authenticated(self) -> bool:
return True
class AuthBackend(AuthenticationBackend):
async def authenticate(self, conn):
print("Authenticate method fired")
return AuthCredentials(["authenticated"]), AuthenticatedUser(
display_name="Test User"
)
class CustomHeaderMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
response = await call_next(request)
print("custom middleware fired")
return response
middleware = [
Middleware(CustomHeaderMiddleware),
Middleware(AuthenticationMiddleware, backend=AuthBackend()),
]
async def starlette_homepage(request):
return JSONResponse({"message": "Hello from Starlette!"})
starlette_app = Starlette(
debug=True,
routes=[
Route("/", starlette_homepage),
],
)
app = FastAPI(middleware=middleware)
@app.get("/")
async def fastapi_homepage():
return {"message": "Hello from FastAPI!"}
app.mount("/starlette", starlette_app)
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)
Running this and going to localhost:8000/
or localhost:8000/starlette
I see:
INFO: 127.0.0.1:51118 - "GET / HTTP/1.1" 200 OK
Authenticate method fired
custom middleware fired
INFO: 127.0.0.1:51129 - "GET /starlette HTTP/1.1" 307 Temporary Redirect
Authenticate method fired
custom middleware fired
INFO: 127.0.0.1:51129 - "GET /starlette/ HTTP/1.1" 200 OK
How can I ensure that the CustomMiddleware
runs first so I can perform token validation before running the AuthenticationMiddleware
and creating the AuthenticatedUser
?
In CustomHeaderMiddleware
you print the message after calling await call_next(request)
.
Change it to print before await call_next(request)
and everything will work:
class CustomHeaderMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
print("custom middleware fired")
response = await call_next(request)
return response
If you need to change the order of middlewares, just change their order in the list of middlewares