I'm currently developing WebSocket microservice using Chalice framework and faced with sudden obstacle with user authentication on connect event. To be more specific: I do not understand how to clearly respond to a client in case he cannot be authenticated.
So far I am using the following approach: client establishes a connection to a WebSocket and afterwards sends a message containing auth token. What I really hate with this approach is that client can connect to a WebSocket without any authentication - he may just ignore sending auth message, thus keeping connected to a WebSocket as long as he wants to.
Fortunately it is allowed to send custom headers on connection and those headers may be easily processed in microservice. The problem is how to respond to a client from within
on_ws_connect()
event with meaningful message or at least return custom status code - main goal here is to notify client with clear message in case he cannot be authenticated and his connection will be dropped.
Attempt to send a message from within on_ws_connect()
:
@app.on_ws_connect()
def ws_connect(event):
app.log.debug(f"New connection established: {event.connection_id}")
event_dict = event.to_dict()
headers = event_dict['headers']
token = headers['Authorization'].split(" ")[1]
try:
auth(token)
except PyJWTError as e:
app.websocket_api.send(event.connection_id, str(e))
app.websocket_api.close(event.connection_id)
fails with:
[ERROR] WebsocketDisconnectedError: DFh2Ffc4oAMCIzw=
Traceback (most recent call last):
File "/var/task/chalice/app.py", line 1583, in __call__
super(WebsocketEventSourceHandler, self).__call__(event, context)
File "/var/task/chalice/app.py", line 1564, in __call__
return self.handler(event_obj)
File "/var/task/app.py", line 14, in ws_connect
app.websocket_api.send(event.connection_id, "User cannot be authenticated. Connection will be dropped.")
File "/var/task/chalice/app.py", line 665, in send
raise WebsocketDisconnectedError(connection_id)
Though in official documentation it is stated that sending message should work in all WS-decorated functions including on_ws_connect()
.
Another possible option is to return custom status code but I also have no idea how to do that. Raising an exception within connect event will return code 502 ("Bad Gateway") which is not descriptive for a client at all.
I would be graceful for any ideas how to deal with that.