Access global context from settings.js

Use case is for building a simple middleware that can validate a Bearer token on a websockets connection, so the initial connection can be rejected if verification fails. Token is stored in global context. Thanks!

Just be aware that middleware for websockets only works on the initial connection as far as I am aware. That means that you cannot have a timeout to automatically end a session for example. You have to add further logic and pass the token with each websocket message.

In order to deal with the global values from the settings.js file, I would do it the other way around, have your own variable/middleware and pass it into the globals section. You can easily write a node.js module to help with this so that the code is in your own file.

I don't feel this is the right approach. There are auth nodes that will check JWT tokens for you. Why not use one of them?

You still need to link those into the process flow. Middleware lets you link into http(s) requests but not into websocket msg exchanges.

Websockets make an initial connection over http(s) and then "upgrade" to ws(s) at which point you no longer have access to the headers typically used to validate JWT tokens.

Also remember that JWT tokens should be short-lived if you really value security since they are subject to hijack/replay attacks. A simple way to help mitigate those is to encode the originating IP address in the token and validate it on each request/msg.

Yes ideally we would handle this at a higher level in the flow similar to HTTP(S) but the websockets implementation doesn't expose the initial request headers or give control to approve the connect request or expire the connection as far as I can see. If anyone had an example of how this has been implemented, either using JWT or something else, that would be really useful.

do you control the websocket server you are connecting to?

https://flows.nodered.org/node/node-red-contrib-websocket-auth0 exists if you use Auth0 (recommended). Last updated a long while ago but would probably point you in the right direction - you might need to for it and update (or look to see if someone else has done so on github).

Yes, this is one of the reasons I use Socket.io in uibuilder.

If you control the websocket server you could put the token in the payload instead...

The websocket server is implemented by NodeRED but if we put the token in the payload the connection will already have been established which isn't ideal, and also there's no option to disconnect a client on Auth failure.

I'm at the point of being able to parse the auth token from the connection request and log it to the console. There's a callback that can return a 401 code on failure but the missing piece is being able to verify the token against one in the context store.

If we can access the context store from settings js, verify the token and do a lookup of a username and pass this on with the payload then that should have everything we need.

Yes, that is correct, I don't believe that the default node can do more than use a middleware function to check the initial client connect.

Even with another library, you still wouldn't be able to disconnect a websocket unless you are including and verifying the token with every ws msg from the client to the server.

We will need input from @knolleary or @dceejay on that but I think that the context store isn't yet created when settings.js is being read. That would be logical anyway since you define any non-standard stores in the settings file.

So I think that you will need to use your own "store".

Again, this only works for the initial connection, beyond that, you have, as far as I am aware, to include the token in every ws msg and validate that.