Simple Password Authentication

Hi all hope all is well.
I've setup a simple user/password authentication receiving stored names a txt file and passwords from a separate txt file for authentication agaisnt the user's input.
I'm struggling to figure out why my authentication process isn't working.
I've setup warning along the code to check variables etc. and to make sure what is typed matches what is read from the files and as far as I can see the code should work fine however it keeps saying that what's typed isn't the same as what is read from the file.
(setup to test the name for now, didn't see why i need to add the extra rules for password if names won't even work yet)
Help would be much appreciated thank you all!

[{"id":"bff02ce1.23867","type":"tab","label":"Authentication Testing","disabled":true,"info":""},{"id":"cf82d211.d074f","type":"function","z":"bff02ce1.23867","name":"","func":"var count = msg.payload.length;\nglobal.set('auth-pass',[]);\n\nfor (var i = 0; i < count; i++){\n    global.set('auth-pass['+i+']',msg.payload[i]);\n    node.warn('pass is '+global.get('auth-pass['+i+']'));\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":30,"wires":[["a97e4542.a7b0a8"]]},{"id":"3966a8fd.031578","type":"file in","z":"bff02ce1.23867","name":"","filename":"Documents/auth-pass.txt","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":360,"y":30,"wires":[["4c980589.e7653c"]]},{"id":"a97e4542.a7b0a8","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1020,"y":30,"wires":[]},{"id":"be61caf9.93a588","type":"inject","z":"bff02ce1.23867","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":30,"wires":[["3966a8fd.031578"]]},{"id":"65c9fd48.d45614","type":"function","z":"bff02ce1.23867","name":"","func":"var count = msg.payload.length;\nglobal.set('auth-name',[]);\n\nfor(var i = 0; i < count ;i++){\n    global.set('auth-name['+i+']',msg.payload[i]);\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":90,"wires":[["e54313fe.92ec3"]]},{"id":"7fb6f436.7ee58c","type":"file in","z":"bff02ce1.23867","name":"","filename":"Documents/auth-name.txt","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":360,"y":90,"wires":[["699a86ee.932998"]]},{"id":"e54313fe.92ec3","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1020,"y":90,"wires":[]},{"id":"102a3316.af08fd","type":"inject","z":"bff02ce1.23867","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":90,"wires":[["7fb6f436.7ee58c"]]},{"id":"4c980589.e7653c","type":"split","z":"bff02ce1.23867","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":570,"y":30,"wires":[["14130ad9.c991b5"]]},{"id":"699a86ee.932998","type":"split","z":"bff02ce1.23867","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":570,"y":90,"wires":[["b3b4796c.cc71c8"]]},{"id":"14130ad9.c991b5","type":"join","z":"bff02ce1.23867","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":720,"y":30,"wires":[["cf82d211.d074f"]]},{"id":"b3b4796c.cc71c8","type":"join","z":"bff02ce1.23867","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":710,"y":90,"wires":[["65c9fd48.d45614"]]},{"id":"ee05d913.760758","type":"ui_text_input","z":"bff02ce1.23867","name":"","label":"","tooltip":"","group":"520f753e.322f2c","order":0,"width":0,"height":0,"passthru":false,"mode":"text","delay":"800","topic":"topic","topicType":"msg","x":80,"y":240,"wires":[["b150c4aa.f4ed48"]]},{"id":"b150c4aa.f4ed48","type":"function","z":"bff02ce1.23867","name":"","func":"msg.payload = msg.payload\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":240,"wires":[["8e891a50.0ff708","76de4152.ff889"]]},{"id":"d4df3b4e.4b8198","type":"ui_text_input","z":"bff02ce1.23867","name":"","label":"","tooltip":"","group":"520f753e.322f2c","order":0,"width":0,"height":0,"passthru":false,"mode":"password","delay":"800","topic":"topic","topicType":"msg","x":100,"y":200,"wires":[["41d8368d.392b08"]]},{"id":"41d8368d.392b08","type":"function","z":"bff02ce1.23867","name":"","func":"msg.payload = msg.payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":200,"wires":[["ac6408f5.4860d8","76de4152.ff889"]]},{"id":"8150a429.2e7648","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":450,"y":370,"wires":[]},{"id":"ac6408f5.4860d8","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":370,"y":160,"wires":[]},{"id":"8e891a50.0ff708","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":370,"y":280,"wires":[]},{"id":"dbc3aacb.9b15b8","type":"ui_button","z":"bff02ce1.23867","name":"","group":"520f753e.322f2c","order":2,"width":0,"height":0,"passthru":false,"label":"button","tooltip":"","color":"","bgcolor":"","icon":"","payload":"user-pass","payloadType":"global","topic":"topic","topicType":"msg","x":120,"y":370,"wires":[["326c62ab.3a83ae","f2d22e38.d640f"]]},{"id":"76de4152.ff889","type":"join","z":"bff02ce1.23867","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":530,"y":220,"wires":[["f8bd78e0.8f1da8"]]},{"id":"326c62ab.3a83ae","type":"function","z":"bff02ce1.23867","name":"","func":"var name = global.get('user-pass['+0+']');\nnode.warn('new = '+name); \nvar authName= global.get('auth-name['+0+']');\nnode.warn('stored = '+authName);\nif (name == authName){\n    msg.payload = 'Valid';\n    return[msg,null];\n}\nelse{\n   msg.payload = name + ' is not '+authName + ' !!!invalid!!!!'\n   return[null,msg];\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":270,"y":370,"wires":[["8150a429.2e7648"],["8150a429.2e7648"]]},{"id":"f2d22e38.d640f","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":130,"y":410,"wires":[]},{"id":"f8bd78e0.8f1da8","type":"function","z":"bff02ce1.23867","name":"","func":"var count = msg.payload.length;\nglobal.set('user-pass',[]);\n\nfor (var i =0;i<count;i++)\n    {\n        global.set('user-pass['+i+']',msg.payload[i]);\n        node.warn('user-pass = '+global.get('user-pass['+i+']'));\n    }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":220,"wires":[["552d313a.67a09"]]},{"id":"5fc3004b.a667e","type":"inject","z":"bff02ce1.23867","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":570,"wires":[["4265a145.9158"]]},{"id":"f18edb9.a530628","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":570,"wires":[]},{"id":"4265a145.9158","type":"function","z":"bff02ce1.23867","name":"","func":"var ar = new Array(2);\nar[0] = global.get('auth-name['+0+']');\nmsg.payload = ar[0].toString();\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":570,"wires":[["f18edb9.a530628"]]},{"id":"552d313a.67a09","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":790,"y":170,"wires":[]},{"id":"96c29b80.f52698","type":"split","z":"bff02ce1.23867","name":"","splt":"1","spltType":"len","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":570,"y":610,"wires":[["f18edb9.a530628"]]},{"id":"520f753e.322f2c","type":"ui_group","name":"Default","tab":"9322de02.138e9","order":1,"disp":true,"width":"6","collapse":false},{"id":"9322de02.138e9","type":"ui_tab","name":"Testing","icon":"dashboard","disabled":false,"hidden":false}]

All you have posted is one function node containing...

var count = msg.payload.length;
global.set('user-pass',[]);

for (var i =0;i<count;i++)
    {
        global.set('user-pass['+i+']',msg.payload[i]);
        node.warn('user-pass = '+global.get('user-pass['+i+']'));
    }
return msg;

... cant tell what is going on with just that.


To get better support, you would be wise to setup a simple flow that has no external dependencies. i.e. use an inject and template node that fakes loading the txt file and then export all the parts that are relevant to your issue.

(Apologies code has been updated should show the whole flow now).

Will try recreating with template as you suggested

Ok so I've tested the exact code but using your "fake" as you suggested then it works perfectly fine...which means the fault must lye within receiving the text from files and converting them to an Array.

In the mean time I did this...

hbSkxJ28A0
8Dh7HlQqgE

[{"id":"cf82d211.d074f","type":"function","z":"bff02ce1.23867","name":"","func":"const lines = msg.payload.split(\"\\n\");\nglobal.set('auth-pass', lines);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":40,"wires":[["a97e4542.a7b0a8"]]},{"id":"a97e4542.a7b0a8","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":710,"y":40,"wires":[]},{"id":"be61caf9.93a588","type":"inject","z":"bff02ce1.23867","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":40,"wires":[["5cf611b2b017c6c3"]]},{"id":"e54313fe.92ec3","type":"debug","z":"bff02ce1.23867","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":710,"y":100,"wires":[]},{"id":"102a3316.af08fd","type":"inject","z":"bff02ce1.23867","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":100,"wires":[["8352b2181b34d9a2"]]},{"id":"326c62ab.3a83ae","type":"function","z":"bff02ce1.23867","name":"","func":"\n\n/** @type {string[]}*/ const users = global.get(\"auth-name\");\n/** @type {string[]}*/ const passwords = global.get(\"auth-pass\");\n\nlet userIdx = users.indexOf(msg.payload.username);\n\nif (userIdx < 0) {\n    msg.payload = `\"${msg.payload.username}\" not found!`\n    return [null, msg];\n}\n\nvar expectedPW = passwords[userIdx];\n\nif (msg.payload.password == expectedPW){\n    msg.payload = 'Valid';\n    return[msg,null];\n}\nelse{\n    msg.payload = `Pasword for \"${msg.payload.username}\" is not wrong!`\n    return [null, msg];\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":240,"y":180,"wires":[["9e2ad9f047ede296"],["98e94693a297ccd1"]]},{"id":"5cf611b2b017c6c3","type":"template","z":"bff02ce1.23867","name":"load pass.txt","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"pass1\npass2\npass3","output":"str","x":330,"y":40,"wires":[["cf82d211.d074f"]]},{"id":"8352b2181b34d9a2","type":"template","z":"bff02ce1.23867","name":"load user.txt","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"user1\nuser2\nuser3","output":"str","x":330,"y":100,"wires":[["fc1b782ed73ca679"]]},{"id":"fc1b782ed73ca679","type":"function","z":"bff02ce1.23867","name":"","func":"const lines = msg.payload.split(\"\\n\");\nglobal.set('auth-name', lines);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":100,"wires":[["e54313fe.92ec3"]]},{"id":"9e2ad9f047ede296","type":"ui_toast","z":"bff02ce1.23867","position":"top right","displayTime":"3","highlight":"green","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"className":"","topic":"","name":"","x":520,"y":160,"wires":[]},{"id":"98e94693a297ccd1","type":"ui_toast","z":"bff02ce1.23867","position":"top right","displayTime":"3","highlight":"red","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"className":"","topic":"","name":"","x":520,"y":200,"wires":[]},{"id":"0b8ef87669a83414","type":"ui_form","z":"bff02ce1.23867","name":"","label":"","group":"520f753e.322f2c","order":7,"width":0,"height":0,"options":[{"label":"Name","value":"username","type":"text","required":true,"rows":null},{"label":"Password","value":"password","type":"password","required":true,"rows":null}],"formValue":{"username":"","password":""},"payload":"","submit":"submit","cancel":"cancel","topic":"topic","topicType":"msg","splitLayout":"","className":"","x":90,"y":180,"wires":[["326c62ab.3a83ae"]]},{"id":"520f753e.322f2c","type":"ui_group","name":"Default","tab":"9322de02.138e9","order":1,"disp":true,"width":"6","collapse":false},{"id":"9322de02.138e9","type":"ui_tab","name":"Testing","icon":"dashboard","disabled":false,"hidden":false}]

That's amazing but not gonna lie it's kind of annoying how fast you did this :joy: . Gonna take me a while to understand your code. your using code I haven't seen before...still on the learning path of this. Half of your code is confusing to me but I'll get it

1 Like

Index of is amazing :joy: it just took out half of my code....didn't know there was code to check if things matched..thank you for that :grin:

There are even better ways if you are interested in learning?

Of course that would be awesome! Still going through your code though. Trying to understand how the "password" portion of your code works.

var expectedPW = passwords[userIdx];

im confused as to how this part gets the correct password if userIdx is only a 0 or -1
shouldn't it fetch nothing or whatever is in postion 0

OH i seee the index changes...added node.warn to check

Since you have 2 arrays (one for users, one for passwords) we need to get the users index so that we can get the users password from the 2nd array.

Here is a heavily commented version.


/** @type {string[]}*/ const users = global.get("auth-name");  //Get the users array
/** @type {string[]}*/ const passwords = global.get("auth-pass");  //Get the password array

let userIdx = users.indexOf(msg.payload.username); //find the index number for entered user name

//at this point, userIdx will be -1 if the user is not found or 0+ if the user was found

if (userIdx < 0) {
   //If the code reaches here, then userIdx is probably -1 (user not found in users array)
    msg.payload = `"${msg.payload.username}" not found!`
    return [null, msg]; //HALT exit the function here - user not found
}

//If the code reaches here, then userIdx is >= 0 (user WAS found in users array - hurray)

//the next line uses the index (0 ~ array length) to GET the password from the passwords array

//e.g. users array = ["user1", "user2", "user3"]
// passwords array = ["pass1", "pass2", "pass3"]
// entering a username of "user2" will set userIdx to 1 (zero based index)
//therefore accessing the index 1 will get password "pass2"

//so this line...
var expectedPW = passwords[userIdx];
//... is similar to  SET   expectedPW   to    passwords[ 2 ]; 

if (msg.payload.password == expectedPW){
    msg.payload = 'Valid';
    return[msg,null]; //Valid, exit function sending output to port 1
}
else{
    msg.payload = `Pasword for "${msg.payload.username}" is not wrong!`
    return [null, msg]; //BAD PASSWORD, exit function sending output to port 2
}

Brilliant thank you so much! Hopefully one day I'll be on your level :joy: . But really thank you means alot!

always willing to learn more if you have more to teach!

Here is a version that uses a faster, simplified approach. The users and passwords are "held together" in JSON instead of separate files and separate arrays.

This version employs a "lookup object" (read more here and here if you wish)

Any how, enough said, this is closer to how i would approach this basic authentication solution...

[{"id":"6c4dcb2453c873f1","type":"debug","z":"1683bd9a.5e0a02","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1450,"y":540,"wires":[]},{"id":"ce9a09756431e7f3","type":"inject","z":"1683bd9a.5e0a02","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":690,"y":540,"wires":[["4c4c1fe2b5b347cd"]]},{"id":"e31a272d9f3a94d0","type":"function","z":"1683bd9a.5e0a02","name":"","func":"\nconst auth = global.get(\"auth\") || {};\n\n//See if auth has a property  (msg.payload.username\nif (!auth.hasOwnProperty(msg.payload.username)) {\n    msg.payload = `\"${msg.payload.username}\" not found!`\n    return [null, msg];\n}\n\n//get password from auth object\nlet expectedPW = auth[msg.payload.username];\nif (msg.payload.password == expectedPW) {\n    msg.payload = 'Valid';\n    return [msg, null];\n} else {\n    msg.payload = `Pasword for \"${msg.payload.username}\" is not wrong!`\n    return [null, msg];\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":620,"wires":[["29a1ba875a59a849"],["27a530718bcb546d"]]},{"id":"4c4c1fe2b5b347cd","type":"template","z":"1683bd9a.5e0a02","name":"load user+pass.txt","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"{\n    \"user1\": \"pass1\",\n    \"user2\": \"pass2\",\n    \"user3\": \"pass3\"\n}","output":"str","x":910,"y":540,"wires":[["0755b8f17a14d6ba"]]},{"id":"29a1ba875a59a849","type":"ui_toast","z":"1683bd9a.5e0a02","position":"top right","displayTime":"3","highlight":"green","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"className":"","topic":"","name":"","x":1130,"y":600,"wires":[]},{"id":"27a530718bcb546d","type":"ui_toast","z":"1683bd9a.5e0a02","position":"top right","displayTime":"3","highlight":"red","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"className":"","topic":"","name":"","x":1130,"y":640,"wires":[]},{"id":"bb68f729257d893c","type":"ui_form","z":"1683bd9a.5e0a02","name":"","label":"","group":"520f753e.322f2c","order":7,"width":0,"height":0,"options":[{"label":"Name","value":"username","type":"text","required":true,"rows":null},{"label":"Password","value":"password","type":"password","required":true,"rows":null}],"formValue":{"username":"","password":""},"payload":"","submit":"submit","cancel":"cancel","topic":"topic","topicType":"msg","splitLayout":"","className":"","x":710,"y":620,"wires":[["e31a272d9f3a94d0"]]},{"id":"1b44ba4a7e41187b","type":"change","z":"1683bd9a.5e0a02","name":"","rules":[{"t":"set","p":"auth","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1260,"y":540,"wires":[["6c4dcb2453c873f1"]]},{"id":"0755b8f17a14d6ba","type":"json","z":"1683bd9a.5e0a02","name":"","property":"payload","action":"","pretty":false,"x":1090,"y":540,"wires":[["1b44ba4a7e41187b"]]},{"id":"520f753e.322f2c","type":"ui_group","name":"Default","tab":"9322de02.138e9","order":1,"disp":true,"width":"6","collapse":false},{"id":"9322de02.138e9","type":"ui_tab","name":"Testing","icon":"dashboard","disabled":false,"hidden":false}]

if you look in side the orange load user+pass.txt you will see the users and passwords are in a STANDARD JSON format. JSON converts directly to JavaScript (it is designed for this kinda thing)

The salient detail is, once the users and passwords are arranged as an key/value object, it can lookup the user VERY fast (since it just accesses the property by name)

e.g.

var passwords = { 
  "user1": "pass1",
  "user2": "pass2"
}
var user_name_entered = "user1";
console.log( passwords[user_name_entered] ); // outputs pass1

Will definitely go through that in detail thank you so much. Just took more of my flow and made it even smaller :joy: why is coding soo annoying sometimes. Think you have something then oops nope here's what u did just better smaller and faster :joy: love it though not gonna lie really amazing to me how code works.

1 Like

Again thank you so much @Steve-Mcl . Your Help has been much appreciated and very very useful thank you so much!

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