This issue attempts to summarize a discussion I had with @bryevdv about overhauling session expiry and provide a token containing a variety of information. The issue with the current mechanism for providing a signed sessions is that it is encoded as part of the Websocket URL which means that it ends up in logs and risks being leaked. Since session ids also never expire this adds additional risks because the other flaw can effectively be exploited until the server is restarted or shut down. Therefore we would like to overhaul both the mechanism by which the token is transmitted and add an expiration to it. This would be done by providing a JWT token to the client which it uses to authenticate itself. This token would then be transmitted using the Websocket subprotocol header.
The JWT token can additionally be used to transmit various information about the original request. One other problem with the bokeh server today is that when running behind a load balancer there is no way to access information about the request such as headers or cookies when the HTTP request and the Websocket connection arrive on different processes. The JWT token could therefore also be used to serialize a variety of information which can then be made available from the session on curdoc().session_context. By default the following should be made available:
Token Valid From time
Token Expiry Time
We could then consider adding the entire request or providing a mechanism by which a user defines what should be made available, e.g. by providing a function which is given the request and returns a JSON serializable dictionary.
The text was updated successfully, but these errors were encountered:
@philippjfr There are several possibilities, some will require investigation/validation of assumptions:
slightly abuse the WS Sec-WebSocket-Protocol header (which is the only header available) to send a token. It was not really meant for this, but apparently people do it. i.e. passing the second arg to the websocket constructor:
const ws = new Websocket(url, "foo")
Should generate a header Sec-WebSocket-Protocol: foo which we could use. A tiny proof of concept of this would be very useful as a first step and in particular we should try to determine if there are any de facto or de jure limitations on the subprotocol header length. This would be my preference, if it can be validated
Move the token authetication in to the protocol itself. I.e., always make a connection but don't create a session until the browser side has sent the auth token as a first websocket message. This complicatates the ws protocol/handshake but is probably not that bad, and is probably my second choice if the subprotocol header approach can't be used.
Store the token in a cookie. This is what Havoc originally proposed. I think this might also be workable but I have less of a feel for how it might work, or how it might change anything tangentially, so it's my least favorite "do something" option.
Lastly there is the "do nothing" option, i.e. leave the token in the ws or was URL. This is definitely less than ideals but if all else fails, as long we have a default and short expiry it might be something livable. With a short expiry the risk here is not so much unfettered access to the app, but that that token might be logged and might contain PII inside. Also this could make ws URLS extremely long.