# FR: Manipulate credentials from runtime

**URL:** <https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683>\
**Category:** Feature Requests\
**Tags:** security\
**Created:** [13 December 2023 16:00 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683 "2023-12-13T16:00:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [13 December 2023 16:00 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/1 "2023-12-13T16:00:52Z")

</div>

> [@Change node credentials at runtime](https://discourse.nodered.org/t/change-node-credentials-at-runtime/19590):
>
> In my node I use an API with OAuth authentication. I save the refresh token in the node credentials. When the access token is refreshed, the API also returns a new refresh token. How can I save the new refresh token in the credentials file at runtime? I already tried it with RED.nodes.addCredentials (node.id, credentials);, but this does not change the credentials file. After a restart, the old refresh token is active again.

Hi Team,  
I propose the following scenario:

Add the following methods to the node object when calling `RED.nodes.createNode`:

- `addCredentialSet(name, cred)`
- `deleteCredentialSet(name)`
- `updateCredentialSet(name, cred)`

Being attached to the node, we cannot define the id when calling credentials methods

To avoid modifying the credential from another node:

```js
// Do not return these new methods when calling RED.nodes.getNode(id)
function getNode(id) {
    var node;
    if (activeNodesToFlow[id] && activeFlows[activeNodesToFlow[id]]) {
        node = activeFlows[activeNodesToFlow[id]].getNode(id,true);
        const { addCredentialSet, deleteCredentialSet, updateCredentialSet, ...safeNode } = node;
        return safeNode;
    }
    ...
    return null;
}

```

So, a node can only modify its credentials

Next, we need to discuss how we update the creds file and the cache  
Hoping I haven't forgotten anything 🤔

---

<div class="post-metadata">

**Author:** ![ralphwetzel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ralphwetzel/32/53713_2.png) [@ralphwetzel](https://discourse.nodered.org/u/ralphwetzel)\
**Post date:** [13 December 2023 16:55 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/2 "2023-12-13T16:55:55Z")

</div>

Sorry if I don't get it. 🤔  
There's an [existing credentials API](https://nodered.org/docs/creating-nodes/credentials). Why would there be a demand for that additional logic?

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [13 December 2023 16:59 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/3 "2023-12-13T16:59:39Z")

</div>

> [@ralphwetzel](#):
>
> Sorry if I don't get it

I think this is about self updating creds - i.e you store a time limited session token in a node, and have it updated, i.e for a refresh token as an example, but only when the node that is updating it - owns those creds - else that could be a **MASSIVE SECURITY ISSUE**

Creds can only be updated from the UI at this stage, at least without getting hackerish.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [13 December 2023 17:04 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/4 "2023-12-13T17:04:42Z")

</div>

The goal as Marcus says is to allow a node to update its credentials which is currently not possible because it is a clone.

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [13 December 2023 17:11 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/5 "2023-12-13T17:11:13Z")

</div>

It has been a long standing principle that the flow/credentials can _only_ be updated via the `/flows` endpoint - ie doing a redeploy from the editor. And that nodes shouldn't be able to rewrite their own configuration.

This has posed some challenges around self-renewing credentials, but we'd need to think through the consequences (and unintended side-effects) of allowing nodes to modify things like this.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [13 December 2023 17:21 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/6 "2023-12-13T17:21:21Z")

</div>

What are the possible consequences?

Currently all developers who update their credentials do so with an external file which involves a lot of external files and if they are not deleted when uninstalling the module a security risk but I digress... why does a node not shouldn't be able to update your credentials?

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [13 December 2023 17:25 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/7 "2023-12-13T17:25:36Z")

</div>

I don't have a quick answer. This has been one of the long standing principles we've stuck to - and I haven't had to think about how/why we came to this conclusion for quite some time.

Certainly one of the issues is around version control and the Projects feature. If nodes can modify the credentials file, then it will have uncommitted changes. If the user reverts the project or deploys to another machine, the credentials will be out of sync.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [13 December 2023 17:34 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/8 "2023-12-13T17:34:16Z")

</div>

Damn, well... since this is not a user action, the version control should not change.  
I don't use the project so I don't know the consequences. Should the credentials be in the versioning?

Let's imagine that it is functional, all good, a user who reverts will in any case have a problem with these outdated credentials

I believe that updating nodes should not perform version control, even if it did there would be problems. By the way how do external files work since they have this problem?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [13 December 2023 18:13 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/9 "2023-12-13T18:13:19Z")

</div>

Agree strongly with Nick here. Changes to the credentials handling should not be rushed and the consequences need to be well understood.

There are plenty of advantages of forcing people to use external files for this and plenty of ways to manage those files, potentially even from Node-RED flows (something else that people need to think about when offloading security processing - you may need to put files where they are read-only to Node-RED itself).

This is a subject that is hard to get right and easy to get wrong.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [13 December 2023 18:55 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/10 "2023-12-13T18:55:30Z")

</div>

So for you, if a node needs to update its credentials it must do so with an external file?

Can't we just ignore the change? I mean it's not done by the user.

Or we create downright a separate file which is only used for the credentials which must be updated, this will help developers not to use crypto?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [13 December 2023 19:22 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/11 "2023-12-13T19:22:44Z")

</div>

> [@GogoVega](#):
>
> must

Not what I said at all.

> [@GogoVega](#):
>
> Can't we just ignore the change? I mean it's not done by the user.
> 
> Or we create downright a separate file which is only used for the credentials which must be updated, this will help developers not to use crypto?

Not helpful rhetoric. And not accurate.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [13 December 2023 19:28 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/12 "2023-12-13T19:28:49Z")

</div>

> [@TotallyInformation](#):
>
> forcing people

😅

I mean, we create a second creds file which will only be used by the new methods (allowing updating from runtime), this allows us not to break version control and it allows centralization of these particular creds

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [13 December 2023 19:40 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/13 "2023-12-13T19:40:01Z")

</div>

But allowing your Node-RED runtime to update its own credentials - even via some new process - poses risks that need to be thought through. I certainly don't know what those risks are, I only know that such a design pattern should not be undertaken lightly or be rushed. Security is an area that, I'm afraid, needs to be taken at a steady pace, not rushed into.

If it were me, I would do my best to avoid having any credentials at all stored in Node-RED but this is a topic all of its own and probably not for this thread. It is a complex area & I am certainly not the best expert on the matter.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [15 December 2023 14:28 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/14 "2023-12-15T14:28:36Z")

</div>

Sorry, my logic may be stupid and for what it's worth...

If a node wants to dynamically store credentials, it will use a file or a database using a file. The potential risk being that the file is not encrypted (or badly) or not deleted when the node is uninstalled.

Since many nodes do it, why not create built-in logic to do it? This reduces these risks. If a developper wants something custom, why not? As credentials are dynamic we can ignore them in versioning and ignore them during the future flows export.

API: currently credentials are not accessible (at least those like passwords)  
Local access: Unfortunately we can't do much, even if the credentials are stored elsewhere, we can access them by looking for the keys in the node configuration

The main risk is the API and a malicious node. The local risk depends on the client and nothing can be done about that (I think)

Please I am not an expert and I just want to evolve this subject which has not really had an answer; if this is not possible then we note it so that we know why

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [15 December 2023 14:55 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/15 "2023-12-15T14:55:37Z")

</div>

> [@GogoVega](#):
>
> why not create built-in logic to do it

Indeed, why not? This is not really about why not, more about whether there is a safe way to do it. It takes time and resources to do it correctly. Doing it in a hurry and making a mistake would be the worst possible outcome.

> [@GogoVega](#):
>
> Please I am not an expert and I just want to evolve this subject which has not really had an answer; if this is not possible then we note it so that we know why

Sometimes your enthusiasm comes across a little forcefully 😀 That is great for some things but there are subject areas where a more measured approach is required. Given that likely everyone with any knowledge in this area is extremely busy already, it comes down to resources and priorities.

My input to this is based on my experiences in Cyber Security and Enterprise Architecture so I know that this can be a minefield area. However, I don't have the detailed knowledge to say exactly what issues there might be and how they might be mitigated. Unfortunately, I also don't have the time to do the research required.

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [15 December 2023 15:03 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/16 "2023-12-15T15:03:45Z")

</div>

One of the reasons we've held back from this is the fact the storage layer of Node-RED is pluggable with a [well defined api](https://nodered.org/docs/api/storage/). It was designed so that any actions that Node-RED needed to do to store data was done via the API, which could result in files on disk, or entries in a database.

Then 3rd party nodes started taking it upon themselves to start writing their own files to disk - without consideration of the storage API and the fact that Node-RED could be running in an environment without a persistent file system. I don't recall (but it has been some time), any specific proposal or request to extend the storage API to support more node-specific storage tasks.

We could certainly look at extending the [storage api](https://nodered.org/docs/api/storage/) to support additional functions. There will be a migration issue to consider - nodes that want to start using the new apis would either just not work in older versions of NR, or need to be written to handle both cases.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [15 December 2023 15:23 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/17 "2023-12-15T15:23:22Z")

</div>

> [@TotallyInformation](#):
>
> a little forcefully

I assure you that this is not intentional 🙂

> [@knolleary](#):
>
> extending the [storage api](https://nodered.org/docs/api/storage/)

This would indeed be a good idea, it would (ideally) eliminate writing other files to disk.

A sort of adminStorage for encrypted data

---

<div class="post-metadata">

**Author:** ![shrickus](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/shrickus/32/517_2.png) [@shrickus](https://discourse.nodered.org/u/shrickus)\
**Post date:** [15 December 2023 18:21 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/18 "2023-12-15T18:21:55Z")

</div>

Interesting discussions here... we too have struggled with managing "transient" data like bearer tokens and session cookies over the years.

It seems safe to say that whatever solution is found should NOT update the file system, as this impacts the project versioning and the storage apis. So perhaps calling this a problem of "updating credentials" is not helpful -- I think we just need some in-memory temporary storage that can be treated like other context variables (albeit with limited access).

Stored credentials could then continue to operate as-is, initializing the config nodes. Any "updates" from the node itself would override them in the config node's memory, and remain in effect until the server is restarted (or they expire, if that could be handled, too).

I'm not suggesting that I have a way to implement any of this, just thinking out loud. Nick and the team will just need time to figure out the best way forward without breaking changes.

---

<div class="post-metadata">

**Author:** ![GogoVega](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gogovega/32/71313_2.png) [@GogoVega](https://discourse.nodered.org/u/GogoVega)\
**Post date:** [16 December 2023 14:01 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/19 "2023-12-16T14:01:56Z")

</div>

> [@shrickus](#):
>
> So perhaps calling this a problem of "updating credentials" is not helpful -- I think we just need some in-memory temporary storage that can be treated like other context variables

You are right, a sort of context specific to each node which writes to disk (the idea is to have persistence - needs to be discussed) and which is not accessible from the editor.

Do we create two, one encrypted by default and the other not?

With this way the credentials are static and if we want dynamic credentials (or something else) we use this new context store.

> [@knolleary](#):
>
> We could certainly look at extending the [storage api](https://nodered.org/docs/api/storage/) to support additional functions.

By rereading the Storage API description, it just allows you to define where the data is written - here we should create a new storage

This may be the best approach

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [16 December 2023 15:47 UTC](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683/20 "2023-12-16T15:47:13Z")

</div>

> [@GogoVega](#):
>
> ...which writes to disk...

except in a cloud environment where disk isn't available - so must support database and/or other as well.

[Next page](https://discourse.nodered.org/t/fr-manipulate-credentials-from-runtime/83683.md?page=2)
