I was wondering if it was possible to pass the results from the dependencies
kwarg in include_router
to the router that is passed to it. What I want to do is decode a JWT from the x-token
header of a request and pass the decoded payload to the books
routes.
I know that I could just write authenticate_and_decode_JWT
as a dependency of each of the routes in routers/book.py, but this would be quite repetitive for a large app.
main.py
from typing import Optional
from jose import jwt
from fastapi import FastAPI, Depends, Header, HTTPException, status
from jose.exceptions import JWTError
from routers import books
app = FastAPI()
def authenticate_and_decode_JWT(x_token: str = Header(None)):
try:
payload = jwt.decode(x_token.split(' ')[1], 'secret key', algorithms=['HS256'])
return payload # pass decoded user information from here to books.router routes somehow
except JWTError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
app.include_router(
books.router,
prefix="/books",
dependencies=[Depends(authenticate_and_decode_JWT)],
)
@app.get("/")
def read_root():
return {"Hello": "World"}
routers/books.py
from fastapi import APIRouter
router = APIRouter()
@router.get('/')
def get_book():
# do stuff with decoded authenticated user data from JWT payload here
pass
@router.post('/')
def create_book():
# do stuff with decoded authenticated user data from JWT payload here
pass
While the answer above about writing a middleware does work, if you don't want a middleware, you just want to use the include_router
, then you can take the authenticate_and_decode_JWT
method and extend it to write the JWT payload into the request
object and then later have your routes read from that out from the request
object.
This way you only need to modify a few lines in your code for it to work:
from fastapi import Request # <== new import
def authenticate_and_decode_JWT(x_token: str = Header(None), request: Request): # <== request is a new param
try:
payload = jwt.decode(x_token.split(' ')[1], 'secret key', algorithms=['HS256'])
request.token_payload = payload # type: ignore # <== store the token payload in request
return payload
except JWTError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
And then read from request
:
from fastapi import Request # <== new import
@router.get('/', request: Request) # <== request is a new param
def get_book():
# do stuff with decoded authenticated user data from JWT payload here
print(request.token_payload) # <== access your token payload