Fastapi: [QUESTION] Raise exception in python-fastApi middleware

Created on 22 Apr 2020  路  11Comments  路  Source: tiangolo/fastapi

I am trying to validate token in fastapi middleware but this seems impossible. As i am thinking middleware needs to make next call although its not required. I am not able to find any good solution to handle token in one go in this python-fastapi backend. Any help is appreciated.

@app.middleware("http")
async def add_middleware_here(request: Request, call_next):
    token = request.headers["Authorization"]
    try:
        verification_of_token = verify_token(token)
        if verification_of_token:
            response = await call_next(request)
            return response
    except InvalidSignatureError as er:
        raise HTTPException(status_code=401)

My expectation is that it should throw 401 error once wrong token is provided.
Instead it throws 500 with below Exception traceback:

Traceback (most recent call last):
  File "c:\users\covered\appdata\local\programs\python\python38\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 385, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "c:\users\covered\appdata\local\programs\python\python38\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "c:\users\covered\appdata\local\programs\python\python38\lib\site-packages\fastapi\applications.py", line 140, in __call__
    await super().__call__(scope, receive, send)
  File "c:\users\covered\appdata\local\programs\python\python38\lib\site-packages\starlette\applications.py", line 134, in __call__
    await self.error_middleware(scope, receive, send)
  File "c:\users\covered\appdata\local\programs\python\python38\lib\site-packages\starlette\middleware\errors.py", line 178, in __call__
    raise exc from None
  File "c:\users\covered\appdata\local\programs\python\python38\lib\site-packages\starlette\middleware\errors.py", line 156, in __call__
    await self.app(scope, receive, _send)
  File "c:\users\covered\appdata\local\programs\python\python38\lib\site-packages\starlette\middleware\base.py", line 26, in __call__
    await response(scope, receive, send)
TypeError: 'NoneType' object is not callable

question

All 11 comments

What kind of behavior do you expect when if verification_of_token: is elsed? Seems like you must raise HTTPException(status_code=401) then.

Also there is also option to use https://fastapi.tiangolo.com/tutorial/dependencies/

What kind of behavior do you expect when if verification_of_token: is elsed? Seems like you must raise HTTPException(status_code=401) then.

Also there is also option to use https://fastapi.tiangolo.com/tutorial/dependencies/

Actually verification_of_token can be true or false depending on token's validity. I am trying to check token here itself before it goes any further. Also InvalidSignatureError error comes up when token is invalid. Now problem is: this always fails the backend here by going in 500 interval server error other than going in 401 unauthorized error. I want to throw 401 error.

I have updated the above problem with exception traceback

According to middleware docs you must either return response or call_next func. Seems like your middleware is not properly throwing a InvalidSignatureError and if block being ignored. So you return None from your middleware which causes exception

So how should i then check validity of token now?

I'd go for something likes. Not sure how's your verify_token func looks like. But it's how to you how you make it) It doesn't seems like FastAPI issue)


def verify_token(token):
       if check_token(token):
           return True
       else:
           return False


@app.middleware("http")
async def add_middleware_here(request: Request, call_next):
    token = request.headers["Authorization"]
    if verify_token(token):
        response = await call_next(request)
        return response
    else:
        raise HTTPException(status_code=401)

I'd go for something likes. Not sure how's your verify_token func looks like. But it's how to you how you make it) It doesn't seems like FastAPI issue)


def verify_token(token):
       if check_token(token):
           return True
       else:
           return False


@app.middleware("http")
async def add_middleware_here(request: Request, call_next):
    token = request.headers["Authorization"]
    if verify_token(token):
        response = await call_next(request)
        return response
    else:
        raise HTTPException(status_code=401)

This totally sounds reasonable but i have already performed this thing and it throws same error as above.

Well, just to be clear I didn鈥檛 tested code above. It was just a graft. Also may be that鈥檚 because you are raising exception instead of returning Response object. Give it a few tries. Also take a look at Dependency based authorization it looks sexy

hey @priyankagupta34 I just came across the same issue, seems weirdly HTTPException doesn't work in middle ware. See https://github.com/tiangolo/fastapi/issues/1125

the comment in there has the solution tho
return Response(content="", status_code=401)

but I agree this is unclear would be good to know if this should be in the documentation or if it's a bug @tiangolo and others think should be addressed. Something like bubbling up if the caught below exception is already of type HTTPException.

This is an intended. So the thing you should do is to return a Response with right status code and message.
See #458

Was this page helpful?
0 / 5 - 0 ratings