Skip to content
Julian Knight edited this page Jan 10, 2018 · 12 revisions

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.

Requirements

  • 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.

Implementation Outline

  • 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)

Node Processing

  • 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

Login function

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.

FE Client Processing

  • 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
  • On receipt of jwt_auth_fail control msg
    • Redirect page to login url OR Make XHR call to login API

Login Resources

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.

Login Page

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.

Login API

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.

To Do

Node

  • 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

Front End

  • Functions to store/retrieve the token from local shared storage.
  • (maybe) Function to call login API, receive token and store.
Clone this wiki locally