Skip to main content

User authentication

Goal

Require username/password from clients. Authentication is configured declaratively with the users: field on the boot config. Each entry has a username, a password (clear text or a pre-computed bcrypt hash), and a list of role names from the standard OPC UA WellKnownRoles.

:::info No callback escape hatch A custom user-manager callback would have to live in a Function-node body — and that body re-runs on every message, so the callback identity would churn and racy state could leak. The palette therefore exposes only the declarative users: field. If your authentication source is dynamic (database, LDAP, single-sign-on), expose it through your own back-end and synchronise the resulting user list into users: at deploy time, not per request. :::

The users: array is part of the config-identity hash, so changing it in the boot Function and redeploying triggers an automatic teardown-then-rebuild. Do not put user-list edits in a node that runs per message.

Inline users

const sterfive = global.get("sterfive");
if (!sterfive) {
node.error("global.get('sterfive') is not set — is the Sterfive OPC UA palette loaded?");
} else {
const { bootstrap, opcua } = sterfive;
const { bootstrapServer } = bootstrap;

const cfg = msg.config || {};

const handle = await bootstrapServer({
port: cfg.port ?? 4840,
endpoint: cfg.endpoint || "node-red-server",
nodesets: ["standard"],
users: [
{ username: "admin", password: "secret", roles: ["AuthenticatedUser", "ConfigureAdmin"] },
{ username: "viewer", password: "$2b$10$...", roles: ["AuthenticatedUser"] },
],
onPopulate: (addressSpace, exposed) => {
const ns = addressSpace.getOwnNamespace();
exposed.myVariable = ns.addVariable({
organizedBy: "RootFolder",
nodeId: "s=MyDynamicVariable",
browseName: "MyDynamicVariable",
dataType: "Double",
value: { dataType: opcua.DataType.Double, value: 0.0 },
});
},
});

flow.set("$myVariable", handle.exposed.myVariable);
flow.set("$opcuaHandle", handle);

node.send({ payload: `OPC UA Server running at ${handle.server.getEndpointUrl()}` });
}

Behind the scenes the helper:

  • Hashes any clear-text password with bcrypt at boot time.
  • Compares incoming ActivateSession credentials with bcrypt.compare.
  • Recognises pre-computed bcrypt hashes ($2a$ / $2b$ / $2y$ prefix) and uses them verbatim.
  • Maps the role names to the WellKnownRoles NodeIds for the OPC UA Roles & Permissions framework.

If you omit users: entirely, the helper installs a default test set (root/secret, gdsadmin/admingds, user1/password1, user2/password2) suitable for development and OPC UA CTT conformance scenarios. Override users: for production.

Helpers exposed for tooling

Two helpers are available on bootstrap for hashing passwords ahead of time:

const { bootstrap } = global.get("sterfive");
const { ensureBcryptHash, isBcryptHash } = bootstrap;

isBcryptHash("$2b$10$..."); // true
ensureBcryptHash("plain"); // returns a bcrypt hash; passes through if already hashed

Use these in a deploy script if you want to commit hashed passwords to a Git-tracked config rather than checking in clear text.

Available role names

The roles: field accepts any standard OPC UA WellKnownRoles name, including:

  • Anonymous
  • AuthenticatedUser
  • Observer
  • Operator
  • Engineer
  • Supervisor
  • ConfigureAdmin
  • SecurityAdmin

Per-node read/write authorization comes from access-level attributes on the variables themselves combined with the role mapping above. The user list controls only session activation and the role NodeIds attached to the session.

Combining with anonymous access

allowAnonymous: false disables anonymous sessions entirely. The default is true. To allow anonymous reads while requiring credentials for writes, leave anonymous on and gate writes via per-variable access-level attributes.

Notes

  • For credentials over the wire, configure at least MessageSecurityMode.Sign (preferably SignAndEncrypt); otherwise the username/password travels in cleartext. See Security policies and certificates.

Next step

Continue with security policies and certificates.

Further reading

For more tips and examples, see the Sterfive book node-opcua by example.