Hi all,
As we all know, currently the dashboard nodes provide a global UI for all users/browsers who access it. I've seen request on this group, and feedback from FRED users where they would like dashboards that present different information for individual users or groups of users.
For example, if data for a sensor coming in from MQTT is ‘owned’ by a certain user or group of users, it should be possible to target dashboards with data that only that user or members of the group are viewing. Similarly, it should be possible to receive input messages from dashboards that indicate which user and/or group they are coming from. It would also be useful to change how the dashboard looks depending on the user that has logged in.
To support all this, we’d need a log in system and a way to protect the dashboard URL from users that haven’t logged in.
Toward addressing this feedback, I’ve started to implement a proof of concept by modifying the dashboard node package.
Proof of concept so far:
Supports a ‘dashboard token’ containing information about the user: specifically, the username and a list of ‘roles’ which are strings. The idea is that a user management system can generate a signed verifiable token (JWT) in a cookie that contains this information for use by the dashboard.
Configuration settings for the dashboard to redirect to a login page if there is no dashboard token presented on connection, set the JWT secret, etc.
If there is a dashboard token, and the dashboard is configured to use it, the system associates every dashboard connection to node red with the username and list of roles contained in the token.
To target a message to a specific user, or role, you include a message property when sending data to the dashboard: 'user' - send message only to this user’s dashboards, 'role' - send message to all user’s dashboards who have this role.
When a message is received by a dashboard, we include the user and roles in the message so that node logic can make requests or process data on a per-user or role basis.
Finally, I’ve added a ‘role’ configuration to the tab nodes. If this is set, tabs will be filtered by role: tabs with an ‘admin’ role will be shown only to users who have this role for example. If no role is specified, all users will be able to view the tab.
Roughly how it works:
We assume a cookie containing a verifiable user name and list of roles is used on connection - using JWT for example. If this cookie is not present we, send a redirect message to the dashboard containing a configurable URL for user log in. (In the PoC I use a simple Node-RED flow for the login URL, and the cookie is not secured yet - work in progress).
Socket.io supports server-side groups called ‘rooms’. When a user connects, we check the cookie and add the socket to a user room, and one or more role rooms. This way we can target users and groups with messages based on message properties.
We associate a client socket with the user and their roles. When messages come in from the UI, we add these to the message before it goes into the flow logic.
When UI updates are sent to the dashboard, we check to see whether the tab roles are in the list of user roles for each socket. If not, the tabs are filtered out so that only users in a given tab role can see the tab. Tabs without a role are displayed to everyone.
For standalone node-red - it might be good to somehow connect this as an option to the built in NR user authentication system. Need to think about how this might be done.
Mike