HTTP request node error 401 "unauthorised" if Node Red Editor credentials activated

NR 3.1.11 working on Raspberry pi

I wanted to secure access to the Node Red editor by uncommenting the Security>adminAuth part in settings.js and change the with Hash security password by mine.
And since then, when I launch my Node Red editor with my credentials, my HTTP request Get node, to display settings of NR ...

it return an unauthorized message code 401:

payload: "Unauthorized"
topic: ""
myIp: "192.168.1.54"
statusCode: 401
headers: object
access-control-allow-origin: "*"
www-authenticate: "Bearer realm="Users""
date: "Wed, 19 Jun 2024 10:44:07 GMT"
connection: "close"
content-length: "12"
x-node-red-request-node: "c48843e0"
responseUrl: "http://192.168.1.54:1880/settings"
redirectList: array[0]
retry: 0

Maybe I made a mistake in the type of credentials? basic authentication?
I tried Digest authentication and it returns “Bad Request”
You can try with this flow after changing the IP address of your NR server and the credentials of the NR publisher

[
    {
        "id": "503b84433ddbc4f5",
        "type": "http request",
        "z": "1dec9bbc.37a314",
        "name": "installedVersion",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "http://192.168.1.54:1880/settings",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "basic",
        "senderr": false,
        "headers": [],
        "x": 810,
        "y": 1650,
        "wires": [
            [
                "5666227af19759e8",
                "bcb627c8cf5e0ef3"
            ]
        ],
        "info": "http://192.168.1.54:1880/settings"
    },
    {
        "id": "5666227af19759e8",
        "type": "debug",
        "z": "1dec9bbc.37a314",
        "name": "NRversion buff",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1010,
        "y": 1680,
        "wires": []
    },
    {
        "id": "a44a30ce418c0458",
        "type": "inject",
        "z": "1dec9bbc.37a314",
        "name": "verif new Version 12h",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "43200",
        "crontab": "",
        "once": true,
        "onceDelay": "20",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 750,
        "y": 1710,
        "wires": [
            [
                "503b84433ddbc4f5"
            ]
        ],
        "info": "360h = 15days\n168h = 7 days"
    },
    {
        "id": "bcb627c8cf5e0ef3",
        "type": "function",
        "z": "1dec9bbc.37a314",
        "name": "actualVersion",
        "func": "//let str = msg.payload;\n\nlet actualVersion = msg.payload.version;//str.substring(31,36);\nmsg.actualVersion = \"v\"+actualVersion;\nreturn msg",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 970,
        "y": 1600,
        "wires": [
            [
                "ea2c4e06c8072d4a"
            ]
        ]
    },
    {
        "id": "ea2c4e06c8072d4a",
        "type": "debug",
        "z": "1dec9bbc.37a314",
        "name": "NRversion",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1030,
        "y": 1640,
        "wires": []
    }
]

Thanks to those who can help me

Hi @SuperNinja

The editor is not using Basic Auth.
it is using a token based authentication.

See below.

https://nodered.org/docs/api/admin/oauth

Great, it works Thanks !
For newbies like me : just type in the RPI terminal:

curl http://localhost:1880/auth/token --data 'client_id=node-red-editor&grant_type=password&scope=*&username=admin&password=password'

by changing admin and password with your credentials
which generates a Token that we copy and paste into the HTTP request Node by setting the Type to “Bearer Autentication”

Last question @marcus-j-davies "expires_in":604800, Does this mean that the token will have to be redone regularly? If yes, how to do it automatically?

Instead of manually CURLing for the token, do it in node-red! Use http request to get and store the token in context, and use the context stored token for further requests.

sorry for this newbie question but how to do it? I tried to put :

http://localhost:1880/auth/token --data 'client_id=node-red-admin&grant_type=password&scope=*&username=xxxx&password=xxxxx'

in the HTTP request node to get a Token, but it doesn't work. I imagine it's not that easy?

Here is one I made earlier :smiley:

You can then store the token (In a context variable)
and pass that to future requests.

This also setups the ability to renew the token

[{"id":"ea1abe3597de3285","type":"change","z":"d38d8fca17d3ca65","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t    \"client_id\": \"node-red-editor\",\t    \"grant_type\" : \"password\",\t    \"scope\": \"*\",\t    \"username\":username,\t    \"password\":password\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":180,"wires":[["428b21b0f67de7d0"]]},{"id":"428b21b0f67de7d0","type":"http request","z":"d38d8fca17d3ca65","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"http://localhost:1880/auth/token","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":610,"y":180,"wires":[["14e5474d9286bea3"]]},{"id":"b3db3e199c65ab14","type":"inject","z":"d38d8fca17d3ca65","name":"","props":[{"p":"username","v":"MyUsername","vt":"str"},{"p":"password","v":"MyPassword","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":210,"y":180,"wires":[["ea1abe3597de3285"]]},{"id":"14e5474d9286bea3","type":"debug","z":"d38d8fca17d3ca65","name":"debug 383","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":830,"y":180,"wires":[]}]

Explanation

This POSTs the property of payload (which is an object to begin with, but is then converted to post data for the API)

payload receives the username and password from the inject to create the requests body that is posted

payload is seen as the main property in Node RED (so HTTP Request Node uses it as the body to POST)

The HTTP Request Node. converts it to post data (application/x-www-form-urlencoded)

I see : to send the Body to the HTTP request node it's a msg.payload object .
Now that I have my Token, if I want to use it to access the Settings I must send an Authorization header like this:
"Authorization: Bearer A_SECRET_TOKEN"

to my HTTP GET node http://localhost:1880/settings

Thanks to Set a request header : Node-RED and Authentication : Node-RED
I sent a msg.headers object {"Authorization": "Bearer A_SECRET_TOKEN"}
and it seems to work :slight_smile: can you confirm that I have it right?

1 Like

That is correct :+1:

You can do the login each time, and use the returned token inline.

or create an interval (inject node)...
To login and store the token using context, for later use.

you can then use that stored token

{
   'Authorization': `Bearer ${flow.get('Token')}`,
   'Other-Header': 'Other Value',
}

Doing the login each time is prob easier

storing to context

flow.set('Token',msg.payload...token...path)

Great ! I learned some new things about NR again, great! :+1:

1 Like

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