Fastapi: How to get token of authenticated user in websocket?

Created on 5 Nov 2020  路  12Comments  路  Source: tiangolo/fastapi

Hi,
I am just trying to get the authenticated user in my websocket endpoint with something like this:

@app.websocket("/api/ws")
async def websocket_endpoint(request: Request, websocket: WebSocket):
    token = request.cookies.get("access_token")
    print(token)
    user = get_user(token)
    if user is None:
        print("lets make it work")
    await manager.connect(websocket, user)
    try:
        while True:
            data = await websocket.receive_text()
            await manager.broadcast(f"#{user.username} says: {data}")
    except WebSocketDisconnect:
        manager.disconnect(websocket, user)
        await manager.broadcast(f"#{user.username} left")

how would I do it ?

question

Most helpful comment

But in the future I recommend reading error messages ;)

All 12 comments

What is stopping the code you have from working?

@Mause First of all thanks for quick reply :) I get Error during WebSocket handshake: Unexpected response code: 500 in browser console

What is the error in your server logs?

server log:

Traceback (most recent call last):
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 154, in run_asgi
    result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/fastapi/applications.py", line 179, in __call__
    await super().__call__(scope, receive, send)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/middleware/errors.py", line 146, in __call__
    await self.app(scope, receive, send)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/exceptions.py", line 58, in __call__
    await self.app(scope, receive, send)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/routing.py", line 283, in handle
    await self.app(scope, receive, send)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/starlette/routing.py", line 57, in app
    await func(session)
  File "/home/ahtisham/ENVS/ENV_COLLAB/lib/python3.8/site-packages/fastapi/routing.py", line 228, in app
    await dependant.call(**values)
TypeError: websocket_endpoint() missing 1 required positional argument: 'request'

@Mause So what do you think ?

@Mause I found there is cookies in websockets so I tried this: token = websocket.cookies.get("access_token") and guess what it worked :) thanks anyways.

You should in fact use the Cookie class

@app.websocket('/')
async def request(websocket: WebSocket, access_token=Cookie(...)):

But in the future I recommend reading error messages ;)

If this has solved your problem, can you please close this issue?

I came across this issue today, too. Maybe it should be documented that the HTTP Request is not available in Websocket endpoints and, instead, the websocket object contains all necessary information?

It is somewhat documented here: https://fastapi.tiangolo.com/advanced/websockets/#using-depends-and-others

In most cases you shouldn't really need to access the Request directly anyway

Thanks a lot for your message! In my case, I was trying to access the app instance through the Request instance, i.e. request.app, as a workaround for #2372 . It took me a while to figure out that the Websocket object, too, contains a reference to the app (websocket.app) and it doesn't seem to be documented anywhere.

Was this page helpful?
0 / 5 - 0 ratings