Securing node.js RESTful services with JWT Tokens

I wanted to create a web service in node. It needed to be stateless, and secure such that only users with the correct credentials could access certain entities. The answer was to use a token. There are a few token modules for node, and I settled on node-jwt-simple. This gives you a JWT (JSON Web Token), which is a:

…means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JavaScript Object Notation (JSON) object that is digitally signed or MACed using JSON Web Signature (JWS) and/or encrypted using JSON Web Encryption (JWE).

To implement this in Node; first, allow users to log in, check they’re ok, and return them a token (I’m using express):

var app = require('express').express();
var jwt = require('jwt-simple');

app.get('/token/', function(req, res) {
	var username = req.headers.username;
	var password = req.headers.password;

	if(checkUser(username, password)) {
		var token = jwt.encode({username: username}, tokenSecret);
		res.json({token : token});
	} else {
		res.json({result: "AuthError"});
	}
});

Notice that I’m sending the username and password as headers. I could be using a post and pass them in the body. I don’t think it really matters. When you create the token, you have the opportunity to set some claims, basically properties of an object. Here I set the username, but if there’s something you need to know about your user, you can put it here.

From the browse I can call this endpoint, passing the username and password in on the header, to retrieve the token:

$.ajax({
	type: "GET",
	cache: false,
	dataType: "json",
	url: "/token/",
	headers: {username:username, password:password},
	success: function(token){
		setToken(token);
	}
});

Back in Node, I can then add some more endpoints to my API, and check the token on each request to ensure it’s valid.

app.get('/XYZ/', function(req, res){
	var decoded = jwt.decode(req.headers.token, tokenSecret);
	if (checkUserCanAccessResource(decoded.username)){
		...
	}
}

The token is read from the header, so you need to add it to each jQuery request:

$.ajax({
	type: "GET",
	cache: false,
	dataType: "json",
	url: "/XYZ/",
	headers: { token:getToken(); },
	success: function(data){
		...
	}
});

This code is only an illustration. You need to think about expiry, error messages etc…