Tag Archives: nodejs

Native NodeJS callbacks with Context

As I mentioned back in September I’ve recently started a new job. Due to the nature of the work I’m not going to be able to talk about much of it. But when there are things I can I’ll try and write them up here.

One of my first tasks has been to write a Node-RED wrapper around a 3rd party native library. This library provides a 2 way communication channel to a prototyping environment so needs to use threads to keep track of things in both directions and make use of callbacks to pass that information back into the Javascript side. I dug around for some concrete examples of what I was trying and while I found a few things that came close I didn’t find exactly what I was looking for so here is a stripped back version of the node I created to use as a reference for later.

This is the C++ method that is called when a new instance of the native node module is created. It takes an object reference as an argument to be stored away and used as the context for the callback later.

void Test::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  if (info.IsConstructCall()) {
    // Invoked as constructor: `new MyObject(...)`
    Test* obj = new Test();
    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());

    v8::Local<v8::Object> context = v8::Local<v8::Object>::Cast(info[0]);
    obj->context.Reset(context);

    uv_loop_t* loop = uv_default_loop();
    uv_async_init(loop, &obj->async, asyncmsg);
  } else {
    // Invoked as plain function `MyObject(...)`, turn into construct call.
    const int argc = 2;
    v8::Local<v8::Value> argv[argc] = { info[0], info[1] };
    v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
    info.GetReturnValue().Set(Nan::NewInstance(cons,argc,argv).ToLocalChecked());
  }
}

The object is created like this on the javascript side where the this is the reference to the object to be used as the context:

function Native() {
  events.EventEmitter.call(this);
  //passes "this" to the C++ side for callback
  this._native = new native.Test(this);
}

We then make the callback from C++ here:

void Test::asyncmsg(uv_async_t* handle) {
  Nan::HandleScope scope;

  //retrieve the context object
  Test* obj = (Test*)((callbackData*)handle->data)->context;
  v8::Local<v8::Object> context = Nan::New(obj->context);

  //create object to pass back to javascript with result
  v8::Local<v8::Object> response = Nan::New<v8::Object>();
  response->Set(Nan::New<v8::String>("counter").ToLocalChecked(), Nan::New(((callbackData*)handle->data)->counter));

  v8::Local<v8::Value> argv[] = { response };
  ((Nan::Callback*)((callbackData*)handle->data)->cb)->Call(context,1,argv);
  free(handle->data);
}

Which ends up back on the javascript side of the house here:

Native.prototype._status = function(status) {
  this.emit("loop", status.counter);
}

I’ve uploaded code to githib here if you want to have look at the whole stack and possibly use it as a base for your project.

Adding 2 Factor Authentication to Your ExpressJS App

Over the last few years barely a week goes by without some mention of a breach at some online organisation and the request to reset passwords does the rounds or we hear about somebody’s account getting compromised.

One method to help reduce the risk of a compromised password is to use something called 2 Factor Authentication. 2FA makes use of the “Something you know, Something you have” approach to authentication. The “Something you know” is your password and the “Something you have” is some form of token. The token is used to generate unique code for each login attempt. There are several different types of token in general use these days.

Hypersecure HyperFIDO token

  • Time based token – These have been around for a while in the form of RSA tokens that companies have been handing out to employees to use with things like VPNs. A more modern variant of this is the Google Authenticator application (Android & iPhone).
  • Smart Card readers – Some banks hand these out to customers, you insert your card into the device, enter your pin number and it generates a one time password.
  • Hardware tokens – These are plugged into your computer and generate a token on demand. An example of these are things like the Yubico neo and the Hypersecur HypeFIDO which implement the Fido U2F standard. At the moment only Chrome supports using these tokens to authenticate with a Website, but there is on going work to add it to Firefox.

In the rest of this post I’m going to talk about adding Google Authenticator and Fido U2F support to a NodeJS/ExpressJS application.

Basic Username/password

Most ExpressJS apps use a plugin middleware called PassortJS to provide authentication. I’ll use this to do the normal username/password stage.

var http = require('http');
var express = require('express');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');

var Account = require('./models/account');
var app = express();

var port = (process.env.VCAP_APP_PORT || process.env.PORT ||3000);
var host = (process.env.VCAP_APP_HOST || '0.0.0.0');
var mongo_url = (process.env.MONGO_URL || 'mongodb://localhost/users');

app.set('view engine', 'ejs');
app.use(passport.initialize());
app.use(passport.session());

passport.use(new LocalStrategy(Account.authenticate()));
passport.serializeUser(Account.serializeUser());
passport.deserializeUser(Account.deserializeUser());

mongoose.connect(mongo_url);

app.use('/',express.static('static'));
app.use('/secure' ensureAuthenticated,passport.,express.static('secure'));

function ensureAuthenticated(req,res,next) {
  if (req.isAuthenticated()) {
    return next();
  } else {
    res.redirect('/login');
  }
}

app.get('/login', function(req,res){
  res.render('login',{ message: req.flash('info') });
});

app.post('/login', passport.authenticate('local', { failureRedirect: '/login', successRedirect: '/secure', failureFlash: true }));

app.get('/newUser', function(req,res){
  res.render('register', { message: req.flash('info') });
});

app.post('/newUser', function(req,res){
  Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
    if (err) {
      console.log(err);
      return res.status(400).send(err.message);
    }

    passport.authenticate('local')(req, res, function () {
      console.log("created new user %s", req.body.username);
      res.status(201).send();
    });
  });
});

var server = http.Server(app);
server.listen(port, host, function(){
  console.log('App listening on  %s:%d!', host, port);
});

Here we have a pretty basic Express app that serves public static content from a directory and renders a login page template with ejs that takes a username and password to access a second “secure” directory of static content. It also has a page to register a new user, all the user information is stashed in a MongoDB database using Mongoose.

Google Authenticator TOTP

Next we will add support for the Google Authenticator app. Here there is a PassportJS plugin (passport-totp) that will handle the actual authentication but we need a way to enrol the site into the application. The app has the ability to read configuration data from a QR code which makes setup simple. In the ExpressJS app we need to add the following routes:

var TOTPStrategy = require('passport-totp').Strategy;
var G2FA = require('./models/g2fa');

app.get('/setupG2FA', ensureAuthenticated, function(req,res){
  G2FA.findOne({'username': req.user.username}, function(err,user){
    if (err) {
      res.status(400).send(err);
    } else {
      var secret;
      if (user !== null) {
        secret = user.secret;
      } else {
        //generate random key
        secret = genSecret(10);
        var newToken = new G2FA({username: req.user.username, secret: secret});
        newToken.save(function(err,tok){});
      }
      var encodedKey = base32.encode(secret);
      var otpUrl = 'otpauth://totp/2FADemo:' + req.user.username + '?secret=' + encodedKey + '&period=30&issuer=2FADemo';
      var qrImage = 'https://chart.googleapis.com/chart?chs=166x166&chld=L|0&cht=qr&chl=' + encodeURIComponent(otpUrl);
      res.send(qrImage);
    }
  });
});

app.post('/loginG2FA', ensureAuthenticated, passport.authenticate('totp'), function(req, res){
  req.session.secondFactor = 'g2fa';
  res.send();
});

2FA Demo App enrolled in Google Authenticator

The first route checks to see if the user has already set up the Authentication app, if not it generates a new random secret and then uses this to build a URL for Google’s Chart API. This API is used to generate a QR code with the enrolment information. As well as the shared secret, the QR code contains the name of the application and the users name so it can easily be identified within the application. The secret is stashed in the MongoDB database along with the username so we can get it back later.

The second route actually verifies the code provided by the application is correct and adds a flag to the users session to say it passed.

The following code is embedded in the in a page to actually show the QR code then to verify that the app is generating the right values.

googleButton.onclick = function setupGoogle() {
  clearWorkspace();
  xhr.open('GET', '/setupG2FA',true);
  xhr.onreadystatechange = function () {
    if(xhr.readyState == 4 && xhr.status == 200) {
      var message = document.createElement('p');
      message.innerHTML = 'Scan the QR code with the app then enter the code in the box and hit submit';
      document.getElementById('workspace').appendChild(message);
      var qrurl = xhr.responseText;
      var image = document.createElement('img');
      image.setAttribute('src', qrurl);
      document.getElementById('workspace').appendChild(image);
      var code = document.createElement('input');
      code.setAttribute('type', 'number');
      code.setAttribute('id', 'code');
      document.getElementById('workspace').appendChild(code);
      var submitG2FA = document.createElement('button');
      submitG2FA.setAttribute('id', 'submitG2FA');
      submitG2FA.innerHTML = 'Submit';
      document.getElementById('workspace').appendChild(submitG2FA);
      submitG2FA.onclick = function() {
        var pass = document.getElementById('code').value;
        console.log(pass);
        var xhr2 = new XMLHttpRequest();
        xhr2.open('POST', '/loginG2FA', true);
        xhr2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xhr2.onreadystatechange = function() {
          if (xhr2.readyState == 4 && xhr2.status == 200) {
            clearWorkspace();
            document.getElementById('workspace').innerHTML='Google Authenticator all setup';
          } else if (xhr2.readyState == 4 && xhr2.status !== 200) {
            clearWorkspace();
            document.getElementById('workspace').innerHTML='Error setting up Google Authenticator';
          }
        }
        xhr2.send('code='+pass);
      }
    } else if (xhr.readyState == 4 && xhr.status !== 200) {
      document.getElementById('workspace').innerHTML ="error setting up Google 2FA";
    }
  };
  xhr.send();
}

Fido U2F

Now the slightly more complicated bit, setting up the U2F support. This is 2 stage process, first we need to register the token with both the site.

app.get('/registerU2F', ensureAuthenticated, function(req,res){
  try{
    var registerRequest = u2f.request(app_id);
    req.session.registerRequest = registerRequest;
    res.send(registerRequest);
  } catch (err) {
    console.log(err);
    res.status(400).send();
  }
});

app.post('/registerU2F', ensureAuthenticated, function(req,res){
  var registerResponse = req.body;
  var registerRequest = req.session.registerRequest;
  var user = req.user.username;
  try {
    var registration = u2f.checkRegistration(registerRequest,registerResponse);
    var reg = new U2F_Reg({username: user, deviceRegistration: registration });
    reg.save(function(err,r){});
    res.send();
  } catch (err) {
    console.log(err);
    res.status(400).send();
  }
});

The first route generates a registration requestion from the app_id, for a simple site this is just the root URL for the site (it needs to be a HTTPS url). This is sent to the webpage which passes it to the token. The token responds with a signed response that includes a public key and a certificate. These are stored away with the username to be used for authentication later.

app.get('/authenticateU2F', ensureAuthenticated, function(req,res){
  U2F_Reg.findOne({username: req.user.username}, function(err, reg){
    if (err) {
      res.status(400).send(err);
    } else {
      if (reg !== null) {
        var signRequest = u2f.request(app_id, reg.deviceRegistration.keyHandle);
        req.session.signrequest = signRequest;
        req.session.deviceRegistration = reg.deviceRegistration;
        res.send(signRequest);
      }
    }
  });
});

app.post('/authenticateU2F', ensureAuthenticated, function(req,res){
  var signResponse = req.body;
  var signRequest = req.session.signrequest;
  var deviceRegistration = req.session.deviceRegistration;
  try {
    var result = u2f.checkSignature(signRequest, signResponse, deviceRegistration.publicKey);
    if (result.successful) {
      req.session.secondFactor = 'u2f';
      res.send();
    } else {
      res.status(400).send();
    }
  } catch (err) {
    console.log(err);
    res.status(400).send();
  }
});

The authentication is a similar process, the first route generates a random challenge and sends this to the website, which asks the token to sign the challenge. This signed challenge is passed back to the site which checks with the public key/certificate that the correct token signed the challenge.

We should now have a site that allows users to register and then enrol both the Google Authenticator app and a Fido U2F token in order to do 2FA.

All the code is for this demo hosted in Github here and a working example is on AWS here.

Flic.io Linux library

As I mentioned I recently got my hands on a set of 4 flic.io buttons. I pretty immediately paired one of them with my phone and started playing. It soon became obvious that while fun, the use cases for a button paired to a phone where limited to a single user environment and not what I had in mind.

What was needed was a way to hook the flic buttons up to something like a Raspberry Pi and Node-RED. While I was waiting for the buttons to arrive I was poking round the messages posted to the indiegogo one of the guys from Shortcut Labs mentioned that such a library was in the works. I reached out to their developer contact point asking about getting access to the library to build a Node-RED node round, I said I was happy to help test any code they had. Just before Christmas I managed got hold of a early beta release to have a play with.

From that I was able to spin up a npm module and a Node-RED node.

The Node-RED node will currently listen for any buttons that are paired with the computer and publish a message as to if it was a single, double or long click

Flic.io Node-RED node

I said I would sit on these nodes until the library shipped, but it appeared on github yesterday so hence this post. The build includes binaries for Raspberry Pi, i386 and x86_64 and needs the very latest Bluez packages (5.36+).

Both my nodes need a little bit of cleaning up and a decent README writing, once that is done I’ll push them to npm.

UPDATE:
Both nodes are now on npmjs.org:
https://www.npmjs.com/package/node-flic-buttons
https://www.npmjs.com/package/node-red-contrib-flic-buttons

WEMO Event notifications

As part of my on going playing with some Belkins WEMO devices I started to have a look at the UPNP Event support.

The UPNP standard as well as including discover and endpoints for control has an event system, this allows devices to publish their status changes to interested parties. The event system uses some extensions to HTTP.

SUBSCRIBE

To subscribe to events from a given device you send a request similar to the following to the eventSubURL given as defined in the setup.xml which is linked to in the UPNP discovery response.

SUBSCRIBE /upnp/event/bridge1 HTTP/1.1
CALLBACK: <http://192.168.1.1:3000/>
NT: upnp:event
TIMEOUT: Second-600
Host: 192.168.1.2:49154

CALLBACK -> is the URL to be notified
TIMEOUT -> how long to send notifications

Gets the following response:

HTTP/1.1 200 OK
DATE: Sun, 11 Jan 2015 18:27:05 GMT
SERVER: Unspecified, UPnP/1.0, Unspecified
CONTENT-LENGTH: 0
X-User-Agent: redsonic
SID: uuid:7206f5ac-1dd2-11b2-80f3-e76de858414e
TIMEOUT: Second-600

SID -> the Subscription ID

The SID is used to identify which notification come from this subscription, it can also be used to renew the subscription before the timeout expires by sending a SUBSCRIBE message like this:

SUBSCRIBE /upnp/event/bridge1 HTTP/1.1
SID: uuid:7206f5ac-1dd2-11b2-80f3-e76de858414e
TIMEOUT: Second-600
Host: 192.168.1.2:49154

NOTIFY

Incoming event notifications get delivered every time the state of the device changes and look like this for the WeMo Socket:

NOTIFY / HTTP/1.1
HOST: 192.168.1.1:3000
CONTENT-TYPE: text/xml; charset="utf-8"
CONTENT-LENGTH: 212
NT: upnp:event
NTS: upnp:propchange
SID: uuid:7206f5ac-1dd2-11b2-80f3-e76de858414e
SEQ: 0

<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
  <e:property>
    <BinaryState>0</BinaryState>
  </e:property>
</e:propertyset>

The events from the light bulbs is a bit more complex, how parse them is demonstrated in the code.

UNSUBSCRIBE

And when your done you can unsubscribe with the following:

UNSUBSCRIBE / HTTP/1.1
Host: 192.168.1.2:49154
SID: uuid:7206f5ac-1dd2-11b2-80f3-e76de858414e

WeMo

Having worked all these bits out I put the following node js app together to test it all out with the WeMo devices I have:

Next step is to put all this together to build a new WeMo node module and then a improved Node-RED node.

Playing with a set of WEMO light bulbs

I’ve been looking things like the Philips Hue since they shipped, but the price had been putting me off (and the fact that they initially only supported iOS devices and only come in screw fit).

When the Belkin WeMo Light Bulbs came round they were a cheaper option and they come in bayonet fit which meant I wouldn’t need to change any of the light fittings in the flat to play with them.

Belkin have created a mobile app to interact with the bulbs, but having to use your phone to turn the light on when you enter a room is bit of a bind. There is a replacement light switch but it’s only available in the US at the moment, so I was looking for other ways to control things. I was looking to hook the lights up to Node-RED so I could drive them based on a whole list of events.

There is a Node-RED node and a bunch of npm modules for controlling WEMO sockets but none of them currently seam to support the light bulbs. So I started to see if I could work out what was needed to get things up and running. As I was going I tweeted some of my progress which led to this exchange:

I decided to not hold my breath while waiting for a useful response and started out with a couple of the existing npm modules.

WEMO devices are all UPNP devices, which means discovering them is actually pretty easy. It also means the interface to interact with them should be pretty self descriptive. The response to the discovery request is a XML document that includes a number of useful things.

  • IP address
  • Port number
  • Unique Device Number
  • List of Services

The list of services has some interesting looking targets, but after some trial and error the bridgeservice turned out to look like the one I wanted. I ended up getting stuck and I was getting ready to set up a separate WiFi network so I could run Wireshark to see how the mobile app was actually driving the lights.

Some sterling work by Jesus Rafael Carrillo (@jescarri on github) on this issue got me the bit of info I was missing.

Taking this I managed to build a simple hard coded app that would turn the lights on and off or set the dim level and the fade times.

EDIT:

Updated here

The next step is to pick one of the existing WEMO npm modules to add this new capability, then update the Node-RED node to go support the new features.

Running Node-Red as a Windows or OSx Service

For a recent project I needed to run Node-RED on windows and it became apparent that being able to run it as a service would be very useful.

After a little poking around I found a npm module called node-windows.

You install node-windows with as follows:

npm install -g node-windows

followed by:

npm link node-windows

in the root directory of your project. This is a 2 stage process as node-windows works better when installed globally.

Now the npm module in installed you configure the Windows service by writing a short nodejs app. This windows-service.js should work for Node-Red

var Service = require('node-windows').Service;

var svc = new Service({
  name:'Node-Red',
  description: 'A visual tool for wiring the Internet of Things',
  script: require('path').join(__dirname,'red.js')
});

svc.on('install',function(){
  svc.start();
});

svc.on('uninstall',function(){
  console.log('Uninstall complete.');
  console.log('The service exists: ',svc.exists);
});

if (process.argv.length == 3) {
  if ( process.argv[2] == 'install') {
    svc.install();
  } else if ( process.argv[2] == 'uninstall' ) {
    svc.uninstall();
  }
}

Run the following to install the service:

node windows-service.js install

and to remove the service:

node windows-service.js uninstall

There is also a OSx version of node-windows called node-mac, the same script with a small change should work on both:

if (process.platform === 'win32') {
  var Service = require('node-windows').Service;
} else if (process.platform === 'darwin') {
  var Service = require('node-mac').Service;
} else {
  console.log('Not Windows or OSx');
  process.exit(1);
}

var svc = new Service({
  name:'Node-Red',
  description: 'A visual tool for wiring the Internet of Things',
  script: require('path').join(__dirname,'red.js')
});


svc.on('install',function(){
  svc.start();
});

svc.on('uninstall',function(){
  console.log('Uninstall complete.');
  console.log('The service exists: ',svc.exists);
});

if (process.argv.length == 3) {
  if ( process.argv[2] == 'install') {
    svc.install();
  } else if ( process.argv[2] == 'uninstall' ) {
    svc.uninstall();
  }
}

I have submitted a pull request to include this in the base Node-RED install.

EDIT:

I’ve added node-linux to the pull request as well to generate /etc/init.d SystemV start scripts.

Node-Red – Delay Node (formally Pause Node)

I’ve just been updating my Pause node for Node-Red after a request to support message rate limiting as well as pausing individual messages.

To help make it a little clearer the node has also been renamed to Delay (thanks to deldrid1 for the suggestion)

Delay Mode

In this mode the node allows you to delay any message passing through it by a given number of milliseconds, seconds, hours or days.

Rate Limit Mode

This time the node ensures that no more than the given number of messages are delivered per millisecond, second, hour or day.

All the code is in my fork of the original project for now and soon to be rolled up in to the main stream.

Node-Red – Digispark RGB Node

Following on from last weekends post about adding a pause node to Node-Red this weekend I’ve been trying to create a node to support my Digispark RGB USB LED.

The RGB shield for the Digispark came with a sketch and a some python code to send colours to the device using the HID protocol. I had a bit of a poke round and I found node-hid and thought things where going to be easy.

Unfortunately just trying to duplicate the python code in nodejs didn’t seam to work no matter what I tried.

After a bit more digging I found this blog post by Dougal Campbell who looked to have been pursuing a similar idea a little earlier in the year. I couldn’t see any follow up post on his blog but a quick comment later and I had pointers to what he’d managed to get working. I was hoping to leave the default sketch on the digiSpark but it needed a little change to the USB library to make things work properly, you can find the changes here.

88-digiRGB.js


// Require main module
var RED = require("../../red/red");
var HID = require('node-hid');
var device;
var node;

// The main node definition - most things happen in here
function DigiRGBNode(n) {
    // Create a RED node
    RED.nodes.createNode(this,n);
    node=this;
    //look up the matching devices
    var devices = HID.devices(0x16c0,0x05df);
    for (var i=0; i< devices.length; i++) {
      if (devices[i].product == 'DigiUSB') {
        path = devices[i].path;
        node.log("found: " + path);
        try {
          device = new HID.HID(devices[i].path);
          //only work with the first one found
          break;
        } catch (e) {
          node.log(e)
        }
      }  
   }
   
   if (device) {   
      this.on("input", function(msg) {
        if (msg != null) {
          var args = msg.payload.split(',');
          if (args.length == 3) {
            device.sendFeatureReport([115,parseInt(args[0]),parseInt(args[1]),parseInt(args[2])]);
          }
        }
      });
   } else {
      node.warn("no digispark RGB found");
   }
   
}

// Register the node by name. This must be called before overriding any of the
// Node functions.
RED.nodes.registerType("digiRGB",DigiRGBNode);


DigiRGBNode.prototype.close = function() {
    // Called when the node is shutdown - eg on redeploy.
    // Allows ports to be closed, connections dropped etc.
    // eg: this.client.disconnect();
    device.close();
}

If you want to have a play unzip 78-digiRGB.zip in the node-red directory to unpack the whole node into the nodes/hardware directory. I have now saved this a Github GIST which you can check out directly into /node-red/nodes/hardware directory as follows:

[user@node node-red]$ git clone https://gist.github.com/6573158.git

You will also need to run npm import node-hid in the node-red directory to add the dependency.

(Remember you will need to modify the DigiUSB.cpp and the usbconfig.h in the DigisparkUSB example as mentioned in the link above).

This is unlikely to make it into core Node-RED as the hardware is a little specialist, but if Nick and Dave decide to host a collection of hardware nodes it may end up in there.

Node-Red – Pause Node

Two guys from my team (Nick O’Leary and Dave Conway-Jones) at IBM released a very cool tool for wiring up IoT last week called Node-Red.

Node-Red lets you wire together a selection of inputs, things like MQTT messages, Twitter feeds, serial port and a whole lot more, perform transforms on them with Javascript functions before outputting them to a similar collection of options.

I’ve been playing with it to replace a couple things that used to be standalone scripts, but one of the things that was missing was the way to delay an action happening until a certain time after a message has arrived. For example if I want to set my Blink(1) clone to green when somebody mentions me in the tweet I may want to reset it to off 20 seconds later

To help with this I have written a new node called pause that delays passing on a given message by a configurable amount of time. Nodes are made up of 2 files and are placed in the node-red/nodes directory. As well as all the built in nodes there is a example node (99-sample) which you can use to

Each node is made up of 2 parts, the first is javascript file which controls how the node should behave and a html file which contains the descriptive text,

99-pause.js

...
// Simple node to introduce a pause into a flow

//Require main module
var RED = require("../red/red");

function PauseNode(n) {
   RED.nodes.createNode(this,n);
   
   this.timeout = n.timeout * 1000;
   
   this.on("input", function(msg) {
       var node= this;
       setTimeout(function(){node.send(msg);}, node.timeout);
   });
}

RED.nodes.registerType("pause",PauseNode);

You can see in the code above I’ve attached a small function to the ‘input’ event for the pause node, all it does setup a callback after the timeout expires to send the passed in message object to the next node in the flow.

99-pause.html

...
<!-- First, the content of the edit dialog is defined.                       -->
<script type="text/x-red" data-template-name="pause">
  <div class="form-row">
     <label for="node-input-topic"><i class="icon-tasks"></i> Pause</label>
    <input type="text" id="node-input-timeout" placeholder="Time">
  </div>
    
  <div class="form-row">
    <label for="node-input-name"><i class="icon-tag"></i> Name</label>
    <input type="text" id="node-input-name" placeholder="Name">
  </div>
</script>

<!-- Next, some simple help text is provided for the node.                   -->
<script type="text/x-red" data-help-name="pause">
    <p>Introduces a pause into a flow</p>
    <p>Default pause is 5 seconds but can be configured</p>
</script>

<!-- Finally, the node type is registered along with all of its properties   -->
<script type="text/javascript">
    RED.nodes.registerType('pause',{
        category: 'function',      // the palette category
        color:"#E6E0F8",
        defaults: {             // defines the editable properties of the node
            name: {value:""},   //  along with default values.
            timeout: {value:"5", required:true, validate:RED.validators.number()}
        },
        inputs:1,                // set the number of inputs - only 0 or 1
        outputs:1,               // set the number of outputs - 0 to n
        icon: "arrow-in.png",    // set the icon (held in public/icons)
        label: function() {      // sets the default label contents
            return this.name||this.topic||"pause";
        },
        labelStyle: function() { // sets the class to apply to the label
            return this.name?"node_label_italic":"";
        }
    });
</script>

The HTML sets up configuration dialog for the node, the help text, the nodes look and behaviour and the default values for any properties the node has.

The configuration dialog for the pause node looks like this:

I’ve checked this new node into my fork of the Node-Red project here, but I’ll be submitting a pull request to get it included in the main project as soon as I get a chance to have a chat with Nick and Dave.

EDIT:
This is now a core node called delay and is also capable of rate limiting messages