Skip to main content

Node.js Guide

Overview

This page shows how to install Node dependencies, run the interactive Node examples, and use the accessor lifecycle in application code.

The Node.js API uses accessor-style classes. A client or server loads a generated .config file, calls initialize(), registers output handlers, and drives actions with provideInput(). The four accessor classes are:

  • SecureCommClient — secure client that connects to servers
  • SecureCommServer — secure server that accepts client connections
  • SecurePublisher — publisher for encrypted messages over MQTT or UDP
  • SecureSubscriber — subscriber that decrypts received messages

The accessors live in entity/node/accessors/ in the iotauth/iotauth repository. Example entities are in entity/node/example_entities/.

Install Node dependencies

The example generation script normally initializes Node dependencies for you. To do it manually:

cd entity/node
npm install

Generate configs

Node example configs are generated from the graph:

cd examples
./generateAll.sh

Generated configs are written under:

entity/node/example_entities/configs/

For example:

entity/node/example_entities/configs/net1/client.config
entity/node/example_entities/configs/net1/server.config

These are JSON files with a .config extension.

Run the interactive Node example

Start Auth 101 first:

cd auth/auth-server
mvn clean install
java -jar target/auth-server-jar-with-dependencies.jar -p ../properties/exampleAuth101.properties

Start a Node server:

cd entity/node/example_entities
node server.js configs/net1/server.config

Start a Node client:

cd entity/node/example_entities
node client.js configs/net1/client.config

Inside the client prompt, start secure communication:

initComm net1.server

Send a message:

send hello from node client

Close communication:

finComm

The server can also send to connected clients:

send hello from node server
sendTo <socketID> hello

Client programming model

const SecureCommClient = require('../accessors/SecureCommClient');

const client = new SecureCommClient('configs/net1/client.config');
client.initialize();

client.setOutputHandler('connected', (connected) => {
if (connected) {
client.provideInput('toSend', Buffer.from('hello'));
}
});

client.setOutputHandler('received', (data) => {
console.log(data.toString());
});

client.setOutputHandler('error', (message) => {
console.error(message);
});

// Initiate secure connection (requests session keys + handshake)
client.provideInput('serverHostPort', { host: 'localhost', port: 21100 });

// Close the connection
client.provideInput('serverHostPort', null);

Server programming model

const SecureCommServer = require('../accessors/SecureCommServer');

const server = new SecureCommServer('configs/net1/server.config');
server.initialize();

server.setOutputHandler('listening', (port) => {
console.log(`listening on ${port}`);
});

server.setOutputHandler('connection', (info) => {
console.log(info);
});

server.setOutputHandler('received', (received) => {
console.log(received.id, received.data.toString());
// Reply to the specific client
server.provideInput('toSend', {
id: received.id,
data: Buffer.from('ack'),
});
});

server.setOutputHandler('error', (info) => {
console.error(info);
});

Publisher and subscriber

The SecurePublisher and SecureSubscriber accessors support encrypted publish-subscribe over MQTT (TCP) or UDP broadcast.

Publisher

const SecurePublisher = require('../accessors/SecurePublisher');

const pub = new SecurePublisher('configs/net1/client.config');
pub.setParameter('numKeysPerRequest', 1);
pub.setParameter('topic', 'Ptopic'); // MQTT topic
pub.initialize();

pub.setOutputHandler('ready', (msg) => {
// Session keys are ready; publish encrypted messages
pub.provideInput('toPublish', Buffer.from('sensor data'));
});

Subscriber

const SecureSubscriber = require('../accessors/SecureSubscriber');

const sub = new SecureSubscriber('configs/net1/server.config');
sub.initialize();

sub.setOutputHandler('received', (received) => {
console.log('topic:', received.topic, 'data:', received.data.toString());
});

// Subscribe to a topic (MQTT) or port (UDP)
sub.provideInput('subscribe', 'Ptopic');

Both accessors default to MQTT over TCP when distProtocol is TCP, and UDP broadcast when distProtocol is UDP.

Delegation and privilege operations

The SecureCommClient supports delegation workflows where a user entity grants access to an agent entity:

// 1. User: obtain a session key ID to delegate
client.getSessionKeyIdForGrantAccess(1, 'HighTrustAgents');
// Prints a JSON key ID to stdout

// 2. Agent: exchange the key ID for actual session keys
client.getSessionKeysForGrantAccess(keyId);
// Prints session keys as JSON to stdout and exits

// 3. User: grant or revoke a delegation privilege
client.performPrivilege('DelegationGrant', subjectEntity, objectResource, '1*day');
client.performPrivilege('DelegationRevoke', subjectEntity, objectResource, null);

client.setOutputHandler('privilege', (result) => {
console.log('privilege result:', result);
});

See entity/node/example_entities/user.js and agent.js for complete delegation examples.

Pre-caching session keys

Entities can request keys in advance to eliminate per-connection Auth round-trips:

// Client: pre-cache keys for server connections
client.getSessionKeysForCaching(3);

// Server: pre-cache keys for future incoming clients
server.getSessionKeysForFutureClients(3);

Common commands in example entities

Client commands (client.js)

CommandMeaning
initComm <serverName>Connect to a named server from targetServerInfoList.
send <message>Send a message over the current secure connection.
sendFile [file]Send file contents (default: data_examples/data.bin).
skReq [numKeys]Request and cache session keys from Auth.
numKeys <n>Set number of keys per request.
showKeysPrint cached distribution/session keys.
showSocketPrint current secure socket state.
finCommClose the secure connection.
migTrigger migration to alternate Auth.

Server commands (server.js)

CommandMeaning
send <message>Send to all connected clients.
sendTo <socketID> <message>Send to one connected client.
skReq [numKeys]Request and cache keys for future clients.
showKeysPrint cached keys.
showSocketPrint connected secure sockets.
finCommClose all connected clients.

When to use Node.js

Use Node.js when:

  • the entity is a gateway, service, demo, or interactive app;
  • event callbacks are more convenient than direct socket handling;
  • you want to integrate secure SST channels with JavaScript application logic;
  • you are using publisher/subscriber style accessors;
  • you need delegation or privilege operations.

Use C for embedded or native targets, lower-level socket control, or file/IPFS encryption.