Setting Websocket Headers dynamically

Hello, I'm currently running on the latest update of NodeRED (v4.0.0-beta.3-1) because of the Websockets new feature that allows you to set headers before the connection request.

The thing is that I need to generate a Bearer token with a POST request before establishing the connection to the websocket.
It works perfectly fine when I manually generate the token and put it into the authorization header of the websocket, but the token last at most an hour, leading me to reset manually the token each time the connection to the websocket close and reconnect or when I restart Node-RED.

Is there a way to change the header of the websocket node before it tries to connect, when the token is no more accepted (I already do that for classic https request and it work perfectly fine) ?

Thanks in advance

Websocket custom http headers are only valid on connection, they are never passed during actual websocket interactions.

That's because the ws protocol does not allow custom headers. What happens is that the initial connection is made over http and is then "upgraded" to ws. You can see this happening if connecting from a browser by checking the network tab in your browser's dev tools. You should see an http connection, then a code 101 upgrade connection which continues over time.

Here is an example - it uses socket.io but the principal is the same:

This page has more details How Do Websockets Work? | Kevin Sookocheff

The upshot is that any authorization header can only be passed in the initial http connection. If you need to continue to pass the bearer token, you have to do it in the websocket message.

So if the site you are connecting to over websockets requires a token refresh each hour (which is about the maximum you should ever do, especially when using JWT because the tokens are subject to token replay attacks), there must be some other mechanism that drives the refresh. You will need to check from a browser or run a background packet capture to find out what is happening. Unless the API you are connecting to has the info in its documentation.

2 Likes

You are right about the http request being upgraded to ws. The point is that if there is an abnormal closure of the connection, the Node RED websocket Node try to reconnect to the websocket (by resending a new http request that will be upgraded).
But if the token is not valid anymore, I'm looking for a way to regenerate the token (I'm actually doing it for classic http request every hour), set a variable containing the token and put it into the custom header of the websocket Node, so I don't need to reset the token manually each time a disconnection append.
I already tried to put the token in environment variable, however I'm not sure I can change the value when a new token is generated.

So I think you will need to do something like watching for the connection error, using a catch node, using that to trigger a flow to regen the token which you capture to a flow context variable.

Hmm, but then you would have to restart the websocket and not sure how to do that.

Actual environment variables are only read when Node-RED starts. However, Node-RED has extended the idea of env variables and allows you to set them in its tabs, groups and sub-flows. I've not tried this but perhaps having the main websocket flow and the catch flow in the same group would let you update the env variable set in the group which the websocket node would use.

This is just speculation though - I've no idea how the websocket node would react.

Thankfully, Node-RED generally gives you alternatives. In this case, the alternatives would either be to create your own websocket custom node (obviously check the flows site first to see if someone already has done this) or possibly to use a function node with a locally required websocket library. Obviously both of these options will require a reasonable amount of JavaScript progamming.

1 Like

I think there is no way to restart the websocket node without restarting Node RED.
I already searched for custom nodes, but there is none for Dynamic Bearer authentication.

I know that my last option is to create a node by myself, but this option would take too long for my project. I think I will use an alternative, but if I have some time, I'll try to create the custom Node.

Thanks for your help

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.