-
-
Notifications
You must be signed in to change notification settings - Fork 92
Security Design
This page aims to set out the requirements and outline design for security for uibuilder.
The aim is to enable JWT capability for both resources (e.g. pages) and Socket.IO connections.
- MUST use JWT.
- MUST be optional (admin switch).
- MUST provide both page and API login capability (MVP: can be external flows). _Though see the section on Login Function and the To Do list for questions on whether page load checks are really required.
- MUST validate token on both page load and receipt of Socket.IO msg from client, MAY validate token on Socket.IO client connection.
- SHOULD validate same client (MVP: IP address check), would have to be optional since not all clients will have stable IP addresses.
- MUST timeout token validity as per best practice for JWT/Token auth.
- MUST be able to work with cookies disabled.
- MAY provide login capability (both API and page logins likely to be required) - MVP: probably handle externally.
NB: "MVP" = Minimum Viable Product.
- Add switch to uibuilder node (rest of the outline assumes switch is on)
-
Uibuilder does NOT check token validity for resource loads (e.g. js/css files) - don’t think that can be differentiated without switching from the static library to
RED.nodeHttp.use()
- "On failure" = Token received from client is not valid OR token is valid but has timed out (now > token expiry timestamp)
- Warn (via control msg & node,warn() ) if not using https
- On request to load (GET/POST/DELETE/etc) from the main path
- Send cookie: Contains URL path & JWT switch status
- Perform token validity check
- On failure
- Call to login function
- On receipt of any Socket.IO msg
- Perform token validity check
- On failure - common
- Send back a control msg to client (jwt_auth_fail)
- Send a control msg to NR (for downstream processing on port 2)
- (Destroy token)?
- On failure - option 1
- Disconnect client
- Call to login function ??
- On failure - Option 2
- Drop incoming msg Allows for the client to take further actions and for node to do further processes if required (future??) Client becomes responsible for re-login.
- On success - process as normal
Particularly where the JWT check fails when loading a page resource, it isn't clear whether the node should redirect to a login page. Possibly, this should be optional since the assumption should be that no sensitive data will be delivered directly, only via Socket.IO and in that case, it doesn't matter if the resources load.
- Decode cookie: JWT switch status (default to false if cookie not available)
- Check for token
- If received
- Add to local storage
- Set token var
- Add to socket query parameter
- If received
- On receipt of jwt_auth_fail control msg
- Redirect page to login url OR Make XHR call to login API
In order to create a token, we have to go through some kind of login process. There are two approaches, both of which need to be supported.
A login page is required where uibuilder is being used to provide a multi-page app. Both the node and the front-end may redirect to the login page. The login page is responsible for capturing the login details and sending them to Node-RED. Node-RED must then combine the data and any other required data such as expiry timestamp, client IP address and encrypt using a given secret. The resulting token must be passed back to the login page. The login page must then put that data into shared storage to allow the uibuilder FE library to access it and return it with every Socket.IO message & page change.
The login API supports a Single Page App (SPA) model similar to Node-RED Dashboard where all resources are in a single HTML page and associated scripts/styles. In this model, no page reloads happen so we do not want to redirect the page to a login page. Instead we need to present a login modal box or a login pseudo-page. This has to be the responsibility of the app designer/developer. The app will call a login REST API in this case, the API call should be standardised and therefore included in the uibuilder FE library.
The API itself should be defined in Node-RED. As an MVP, the API could be external to uibuilder but in that case, the validation of the token also has to be external or the token secret has to be made available to uibuilder.
The API must return a valid token that the client page must store in shared storage. This should be standardised in the uibuilder FE library.
- Decide if Socket.IO connection check is really needed (
io.use()
) - probably not if we want to allow a channel to stay open for control messages. - Decide if JWT check should be done on page loads or not - see Login Function. And/Or decide whether that should be optional.
- Move JWT Secret out of node settings - Current location is not secure - probably needs to be external for now (MVP) along with validation code to support an external flow for login processing.
- (maybe) Work out how to limit JWT checks to page resources and not images, styles, scripts
- Functions to store/retrieve the token from local shared storage.
- (maybe) Function to call login API, receive token and store.
Please feel free to add comments to the page (clearly mark with your initials & please add a commit msg so we know what has changed). You can contact me in the Discourse forum, or raise an issue here in GitHub! I will make sure all comments & suggestions are represented here.
-
Walkthrough 🔗 Getting started
-
In Progress and To Do 🔗 What's coming up for uibuilder?
-
Awesome uibuilder Examples, tutorials, templates and references.
-
How To
- How to send data when a client connects or reloads the page
- Send messages to a specific client
- Cache & Replay Messages
- Cache without a helper node
- Use webpack to optimise front-end libraries and code
- How to contribute & coding standards
- How to use NGINX as a proxy for Node-RED
- How to manage packages manually
- How to upload a file from the browser to Node-RED
-
Vanilla HTML/JavaScript examples
-
VueJS general hints, tips and examples
- Load Vue (v2 or v3) components without a build step (modern browsers only)
- How to use webpack with VueJS (or other frameworks)
- Awesome VueJS - Tips, info & libraries for working with Vue
- Components that work
-
VueJS v3 hints, tips and examples
-
VueJS v2 hints, tips and examples
- Dynamically load .vue files without a build step (Vue v2)
- Really Simple Example (Quote of the Day)
- Example charts using Chartkick, Chart.js, Google
- Example Gauge using vue-svg-gauge
- Example charts using ApexCharts
- Example chart using Vue-ECharts
- Example: debug messages using uibuilder & Vue
- Example: knob/gauge widget for uibuilder & Vue
- Example: Embedded video player using VideoJS
- Simple Button Acknowledgement Example Thanks to ringmybell
- Using Vue-Router without a build step Thanks to AFelix
- Vue Canvas Knob Component Thanks to Klaus Zerbe
-
Examples for other frameworks (check version before trying)
- Basic jQuery example - Updated for uibuilder v6.1
- ReactJS with no build - updated for uibuilder v5/6
-
Examples for other frameworks (may not work, out-of-date)
-
Outdated Pages (Historic only)
- v1 Examples (these need updating to uibuilder v2/v3/v4/v5)