Uibuilder security

I am trying to secure a uibuilder site with the help of the built-in security. I have built a small example from the default page. Actually, when the button is pressed, a record should be read from a database and sent to the uibuilder. But my problem already shows up in the small example.
isAuthorised remains false and the uibuilder does not accept any messages from Node-RED.
it runs on Ubuntu 18.04.5 LTS
Node-RED version: v1.3.5
Node.js version: v16.4.1
uibuilder version: 4.0.1
I would be grateful for a hint what I am doing wrong.

[{"id":"1d1b3bd6.e0e46c","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"bf01ad16.3d31b8","type":"inject","z":"1d1b3bd6.e0e46c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":120,"wires":[["b6383a10.69a8d"]]},{"id":"b6383a10.69a8d","type":"uibuilder","z":"1d1b3bd6.e0e46c","name":"","topic":"","url":"sectest","fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"templateFolder":"blank","extTemplate":"","showfolder":false,"useSecurity":true,"sessionLength":432000,"tokenAutoExtend":true,"reload":false,"x":420,"y":120,"wires":[["8d530e57.7ffc6"],["defc2046.348288","a41a5c1.b9d882"]]},{"id":"8d530e57.7ffc6","type":"debug","z":"1d1b3bd6.e0e46c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":595,"y":60,"wires":[],"l":false},{"id":"defc2046.348288","type":"debug","z":"1d1b3bd6.e0e46c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":595,"y":160,"wires":[],"l":false},{"id":"6c9b305c.77cd8","type":"link in","z":"1d1b3bd6.e0e46c","name":"","links":[],"x":195,"y":180,"wires":[["b6383a10.69a8d"]]},{"id":"a41a5c1.b9d882","type":"link out","z":"1d1b3bd6.e0e46c","name":"","links":[],"x":595,"y":120,"wires":[]},{"id":"899f7ce7.24a34","type":"comment","z":"1d1b3bd6.e0e46c","name":"index.js","info":"/* jshint browser: true, esversion: 5, asi: true */\n/*globals Vue, uibuilder */\n// @ts-nocheck\n/*\n  Copyright (c) 2021 Julian Knight (Totally Information)\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n*/\n'use strict'\n\n/** @see https://totallyinformation.github.io/node-red-contrib-uibuilder/#/front-end-library */\n\n// eslint-disable-next-line no-unused-vars\nconst app = new Vue({\n    el: '#app',\n\n    data() { return {\n        msgRecvd    : 'nothing received',\n        msgSent     : 'nothing sent',\n        \n        isLoggedOn  : false,\n        userId      : null,\n        userPw      : null,\n        inputId     : '',\n        inputPw     : '',\n    }}, // --- End of data --- //\n\n    computed: {\n\n    }, // --- End of computed --- //\n\n    methods: {\n\n        doLogon: function() {\n            uibuilder.logon( {\n                'id': this.inputId,\n                'password': this.inputPw,\n            } )\n        }, // --- End of doLogon --- //\n\n        doLogoff: function() {\n            uibuilder.logoff()\n        }, // --- End of doLogon --- //\n\n       \n        doTest: function() {\n            uibuilder.send({'payload': \"Test\"})\n        },\n\n    }, // --- End of methods --- //\n\n    // Available hooks: beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed, activated,deactivated, errorCaptured\n\n    /** Called after the Vue app has been created. A good place to put startup code */\n    created: function() {\n\n        // Example of retrieving data from uibuilder\n        this.feVersion = uibuilder.get('version')\n\n        /** **REQUIRED** Start uibuilder comms with Node-RED @since v2.0.0-dev3\n         * Pass the namespace and ioPath variables if hosting page is not in the instance root folder\n         * e.g. If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages.\n         * e.g. uibuilder.start('/uib', '/uibuilder/vendor/socket.io') // change to use your paths/names\n         * @param {Object=|string=} namespace Optional. Object containing ref to vueApp, Object containing settings, or String IO Namespace override. changes self.ioNamespace from the default.\n         * @param {string=} ioPath Optional. changes self.ioPath from the default\n         * @param {Object=} vueApp Optional. Reference to the VueJS instance. Used for Vue extensions.\n         */\n        uibuilder.start(this) // Single param passing vue app to allow Vue extensions to be used.\n\n        //console.log(this)\n\n    }, // --- End of created hook --- //\n\n    /** Called once all Vue component instances have been loaded and the virtual DOM built */\n    mounted: function(){\n\n        //console.debug('[indexjs:Vue.mounted] app mounted - setting up uibuilder watchers')\n\n        var app = this  // Reference to `this` in case we need it for more complex functions\n\n        // If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO\n        uibuilder.onChange('msg', function(msg){\n            console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', msg)\n            app.msgRecvd = msg\n        })\n\n        //#region ---- Debug info, can be removed for live use ---- //\n\n        /** You can use the following to help trace how messages flow back and forth.\n         * You can then amend this processing to suite your requirements.\n         */\n\n        // If we receive a control message from Node-RED, we can get the new data here - we pass it to a Vue variable\n        uibuilder.onChange('ctrlMsg', function(msg){\n            console.info('[indexjs:uibuilder.onChange:ctrlMsg] CONTROL msg received from Node-RED server:', msg)\n        })\n\n        /** You probably only need these to help you understand the order of processing\n         * If a message is sent back to Node-RED, we can grab a copy here if we want to\n         */\n        uibuilder.onChange('sentMsg', function(msg){\n            console.info('[indexjs:uibuilder.onChange:sentMsg] msg sent to Node-RED server:', msg)\n            app.msgSent = msg\n        })\n\n        /** If we send a control message to Node-RED, we can get a copy of it here */\n        uibuilder.onChange('sentCtrlMsg', function(msg){\n            console.info('[indexjs:uibuilder.onChange:sentCtrlMsg] Control message sent to Node-RED server:', msg)\n        })\n\n        /** If Socket.IO connects/disconnects, we get true/false here */\n        uibuilder.onChange('ioConnected', function(connected){\n            console.info('[indexjs:uibuilder.onChange:ioConnected] Socket.IO Connection Status Changed to:', connected)\n        })\n        /** If Server Time Offset changes */\n        uibuilder.onChange('serverTimeOffset', function(serverTimeOffset){\n            console.info('[indexjs:uibuilder.onChange:serverTimeOffset] Offset of time between the browser and the server has changed to:', serverTimeOffset)\n        })\n\n        /** If user is logged on/off */\n        uibuilder.onChange('isAuthorised', function(isAuthorised){\n            console.info('[indexjs:uibuilder.onChange:isAuthorised] isAuthorised changed. User logged on?:', isAuthorised)\n            console.log('authData: ', uibuilder.get('authData'))\n            console.log('authTokenExpiry: ', uibuilder.get('authTokenExpiry'))\n            app.isLoggedOn = isAuthorised\n            console.log(uibuilder.get('version'))\n                 \n        })\n\n        //#endregion ---- Debug info, can be removed for live use ---- //\n\n    }, // --- End of mounted hook --- //\n\n}) // --- End of app1 --- //\n\n// EOF","x":330,"y":240,"wires":[]},{"id":"3a1f7211.65edfe","type":"comment","z":"1d1b3bd6.e0e46c","name":"index.html","info":"<!doctype html>\n<html lang=\"en\"><head>\n\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n    <title>Node-RED UI Builder - VueJS + bootstrap-vue default template</title>\n    <meta name=\"description\" content=\"Node-RED UI Builder - VueJS + bootstrap-vue default template\">\n\n    <link rel=\"icon\" href=\"./images/node-blue.ico\">\n\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css\" />\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css\" />\n    <!-- Your own CSS -->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"./index.css\" media=\"all\">\n\n</head><body>\n\n    <div id=\"app\" v-cloak>\n        <b-container id=\"app_container\">\n            <h2>Simple Logon/Logoff form</h2>\n            <b-form class=\"border p-3 m-2\">\n                <p v-if=\"! isLoggedOn\">\n                    <b-form-input v-model=\"inputId\" type=\"text\" placeholder=\"Enter user id to logon\"></b-form-input><br>\n                    <b-form-input v-model=\"inputPw\" type=\"password\" placeholder=\"Enter user password to logon\"></b-form-input><br>\n                    <b-button id=\"btn_logon\" pill variant=\"primary\" v-on:click=\"doLogon\">Log On</b-button>\n                </p>\n                <p v-if=\"isLoggedOn\">\n                    <b-button id=\"btn_logoff\" pill variant=\"primary\" v-on:click=\"doLogoff\">Log Off</b-button>\n                </p>\n                <b-button id=\"btn_test\" pill variant=\"secondary\" v-on:click=\"doTest\">Send and receive test message</b-button>\n                <p>Sent: {{ msgSent }}</p>\n                <p>Received: {{ msgRecvd }}</p>\n            </b-form>\n        </b-container>\n    </div>\n\n    <!-- These MUST be in the right order. Note no leading / -->\n\n    <!-- REQUIRED: Socket.IO is loaded only once for all instances. Without this, you don't get a websocket connection -->\n    <script src=\"../uibuilder/vendor/socket.io/socket.io.js\"></script>\n\n    <!-- Vendor Libraries - Load in the right order, use minified, production versions for speed -->\n    <script src=\"../uibuilder/vendor/vue/dist/vue.js\"></script> <!-- dev version with component compiler -->\n    <!-- <script src=\"../uibuilder/vendor/vue/dist/vue.min.js\"></script>   prod version with component compiler -->\n    <!-- <script src=\"../uibuilder/vendor/vue/dist/vue.runtime.min.js\"></script>   prod version without component compiler -->\n    <script src=\"../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js\"></script> <!-- Dev version -->\n    <!-- <script src=\"../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.min.js\"></script>   Prod version -->\n\n    <!-- REQUIRED: Sets up Socket listeners and the msg object -->\n    <script src=\"./uibuilderfe.js\"></script> <!-- dev version -->\n    <!-- <script src=\"./uibuilderfe.min.js\"></script>     prod version -->\n\n    <!-- OPTIONAL: You probably want this. Put your custom code here -->\n    <script src=\"./index.js\"></script>\n\n</body></html>","x":460,"y":240,"wires":[]}]

Hopefully you have read the caveats for the current releases? The security features are still in development.

Also, please check out this recent thread where I summarised how security is supposed to work and which bits might actually work at the moment.

In there is also an offer to create a new branch of uibuilder so that people can collaborate on the security features.

From your posted image, I can see that you have sent a msg with msg._auth.id set to null which will never work as that is the one piece of information you absolutely must supply since nothing makes any sense without it. That is all documented in the technical docs.

Thank you for your answer. Yes, I had read that security is still in development. But I thought isAuthorised always remains false because I'm doing something wrong.
I don't think I understand enough about the topic to actively participate the development. Obviously by the fact that I've read the technical docs and a lot of other stuff, and still don't understand some of it.
I also tried to send msg._auth, but it always came up as null.
In the meantime, the login works so far. I will follow the further development with interest.

1 Like

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