1

I’m building a secure messaging app using FastAPI with JWT authentication and websockets.

My issue is that after the client connects with a valid token, the websocket closes right away with code 1006.

Here’s the relevant part of my code:

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, token: str):
 try:
 payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
 await websocket.accept()
 await websocket.send_text("Connected!")
 except Exception as e:
 print(e)
 await websocket.close()

How can I correctly verify the JWT before accepting the websocket so that the connection stays open?

vimuth
5,87355 gold badges98 silver badges128 bronze badges
asked Oct 30 at 19:16
1
  • 1006 means the socket was closed abnormally, most likely because FastAPI rejected the WebSocket before it was actually accepted. What I believe is you are accepting the WebSocket after reading the token parameter. But WebSockets don’t pass query parameters the same way as HTTP, and FastAPI expects websocket.accept() to happen before most interactions. Also, if token is invalid, the browser closes the socket abruptly (1006), because WebSockets cannot receive normal HTTP 401/403 responses. Commented Oct 30 at 19:27

2 Answers 2

0

WebSocket connections need to be kept alive with a message loop.

from fastapi import WebSocket, WebSocketDisconnect, status
import jwt
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, token: str):
 # Verify token BEFORE accepting
 try:
 payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
 user_id = payload.get("user_id")
 except jwt.InvalidTokenError:
 await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Invalid token")
 return
 
 # Now accept the connection
 await websocket.accept()
 
 try:
 await websocket.send_json({"type": "connection", "message": "Connected successfully"})
 
 # Message loop - keeps connection alive
 while True:
 message = await websocket.receive_text()
 
 # Your message handling logic
 await websocket.send_json({
 "type": "echo",
 "data": message,
 "user_id": user_id
 })
 
 except WebSocketDisconnect:
 print(f"User {user_id} disconnected")
 except Exception as e:
 print(f"Error for user {user_id}: {e}")
 await websocket.close(code=1011)

CLIENT-SIDE (in javascript):

const ws = new WebSocket(`ws://localhost:8000/ws?token=${jwtToken}`);
ws.onopen = () => {
 console.log('Connected');
};
ws.onmessage = (event) => {
 console.log('Message:', event.data);
};
ws.onerror = (error) => {
 console.error('WebSocket error:', error);
};
ws.onclose = (event) => {
 console.log('Closed:', event.code, event.reason);
};
// Send messages
ws.send('Hello server!');
answered Oct 31 at 6:21
Sign up to request clarification or add additional context in comments.

Comments

0

I'm going to keep the JWT part of your question out of my answer, because it's unrelated to the issue of the connexion closing.

Once you understand why, you can easily add back your token verification.

Sample code that closes the connexion

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
 await websocket.accept()
 await websocket.send_text("Connected!")

We accept the connexion, send a message, and... the function ends, so FastAPI closes the connexion.

Sample code that keeps it alive

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
 await websocket.accept()
 await websocket.send_text("Connected!")
 while True:
 message = await websocket.receive_text()
 print(f"Received message: {message}")

Here, after sending "Connected!", we keep listening on the websocket (forever).

Now, it's up to you to add your logic:

  • When do you actually close the connexion?

  • Your token verification

Hope that helps!

answered Oct 31 at 10:02

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.