Reputation: 1329
I have a AsyncWebSocketConsumer
which first authorizes a user's credential cookies before accepting their connection, as so:
// consumer.py
class AuthWebSocketConsumer(AsyncWebSocketConsumer):
async def connect(self):
if not(await self.authorized(self.scope)):
await self.close(code=4004)
else:
await self.accept()
However, on the client side, I am seeing this as an onerror
event followed by an onclose
event with a Websocket code of 1006
, not 4004
as I sent back.
// socket.js
this.log_socket = new WebSocket(url.href);
this.log_socket.onerror = (event) => {
// Happens on Websocket REJECTs
console.log("Socket error", event);
};
this.log_socket.onclose = (event) => {
console.log("Socket closed: ", event);
};
The logged close event being as so
CloseEvent {isTrusted: true, wasClean: false, code: 1006, reason: "", type: "close", …}
bubbles: false
cancelBubble: false
cancelable: false
code: 1006
It seems either Django channels is not forwarding the websocket close code, or the browser is masking the error code as the connection was never accepted. In which case, what is the proper way to relay to the client that they are not authenticated for Websocket connects (or some other rejection reason)? It seems at the moment, I need to accept the connection before immediately closing it - which seems a little bit like a security flaw?
Upvotes: 3
Views: 2875
Reputation: 224
I had the same problem once and solved it like follows:
// consumer.py
class AuthWebSocketConsumer(AsyncWebSocketConsumer):
async def connect(self):
await self.accept()
if not(await self.authorized(self.scope)):
await self.close(code=4004)
I saw someone's comment on stackoverflow. It said that you need to accept the connection first to send the close code. Unfortunately I wasn't able to find the original comment.
Upvotes: 5