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.