Implementing Token-Based Authentication With jwt-simple

On this post, we will talk about JSON Web Tokens, most commonly known by its acronym JWT. If you have done any web development work for the last few years, you must have heard of it, or even used a package that uses JWT to implement a token-based authentication mechanism under the hood.

We will examine what a JWT is and describe what comprises a valid token. Next, we will implement basic authentication using Node/Express and the jwt-simple package.

What is JWT?

According to the comprehensive Introduction to JSON Web Tokens:

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA.

JWT is said to be compact because it uses JSON which is pretty much how every web application these days pass data across consumers and other APIs. That means that a JWT can be easily passed around as a query parameter, through a POST request, or through request headers. Being self-contained adds up to the portability because it means that it can contain the needed information in the token itself. We will see this in practice in our small Express application.

Anatomy of JSON Web Tokens

A JSON Web Token is made up of three parts that are separated by dots. The first two parts are called Header and Payload, respectively. Both of them are Base64 encoded JSON objects that contain several information that we are going to briefly discuss below.

The Header object contains the type of the token and the encryption algorithm used. Since we are going to create a basic authentication mechanism on an Express app, the type is JWT and the encryption will be a keyed-hash message authentication code (HMAC). Since we will use a package which will simplify the encoding and decoding of our tokens, there is no need to set this explicitly and we will stick with the defaults which is HMAC SHA256.

The Payload contains what the specification refers to as claims. They are information that can be attached to the token for identification or verification purposes. Claims are further categorized as Registered ClaimsPublic Claims and Private Claims. On our example app, we will use Registered Claims to identify our application as the Issuer of the token and to set its expiry. We will also make use of the user's name and their password as Public Claims.

Now that we have discussed the first and the second part of a JWT, it is now time for the third one, which is called the Signature. Once we have the Header and the Payload properly encoded as a Base64 strings, they need to be concatenated with a dot, and then hashed with the app secret. This process will produce the token's signature. The secret can be any string, but as the name suggests, keep it secret because it can be used to decode your token's Header and Payload.

Here's an example token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0ODk5OTEyNjI3NTIsImlzcyI6IkpvaG4gQ3Jpc29zdG9tbyIsIm5hbWUiOiJjcmlzb3N0b21vIiwiZW1haWwiOiJjcmlzb3N0b21vQGpvaG4uY29tIn0._CP8KU_AX4XNJKyxD561LTiFbY0HcPFKRgI1AztGMsI

Try to notice the dots that separate the three parts of the token. To wrap this section up and as a review, the first two parts are the Base64 encoded JSON objects that contains information about the user and our application. The third part is hashed version of the first two parts with the application key used as the hash key.


Application Demo

It is now time for the application demo. At this point, we already have a good grasp of what a JSON Web Token is and its parts. We are now ready to put this into practice by creating a demo application to solidify the concepts that we have learned. Before we start, a word of precaution:

The example app that we will build in this section will be for the sole purpose of understanding how JWT can be used to implement a barebones token-based authentication. Please do not use this example in production. There are better packages out there that uses jwt-simple under the hood and makes this process foolproof.

Dependencies

Creating the user store and the token store

Since this is a fairly small project, we will not use any real databases. Instead, the users will be hard coded in an array, as well as the tokens. We will create two files to implement these functionalities in this section.

USERS.JS

const users = [
  { _id: 1, name: "john", email: "john@crisostomo.com", password: "john12345" },
  { _id: 2, name: "crisostomo", email: "crisostomo@john.com", password: "crisostomo12345" },
];

function validateUser(username, password) {
  const user = users.find((user) => {
    return user.name === username && user.password === password;
  });

  return user;
}

module.exports = { validateUser };

TOKENS.JS

const tokens = [];

module.exports = {
  add: function(token, payload) {
    tokens[token] = payload;
  },

  isValid: function(token) {
    if (!tokens[token]) {
      return false; 
    }

    if (tokens[token].exp <= new Date()) {
      const index = tokens.indexOf(token);
      tokens.splice(index, 1);
      return false;
    } else {
      return true;
    }
  }
}

On our users.js file, we exposed a convenience method to let us easily validate a user by searching through our users array. Our token.js file allows us to add a token with the associated payload. It also has a method that can check a token's validity.

Creating our application

This is where we create our application. Our app will have two entry points: one for accessing a restricted route, and another one where we can obtain tokens for registered users. The endpoint for these functionalities are /secretInfo and /token.

On a high level, we can obtain a valid token if we send a POST request to the /token endpoint with valid user credentials. This token can then be used to access the information at /secretInfo.

The first thing that we need to do is to require the dependencies mentioned above, and set the server to run at port 8080:

const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jwt-simple');
const moment = require('moment');
const users = require('./users');
const tokens = require('./tokens');

const app = express();
app.use(bodyParser.json());

const jwtAttributes = {
  SECRET: 'this_will_be_used_for_hashing_signature',
  ISSUER: 'John Crisostomo', 
  HEADER: 'x-jc-token', 
  EXPIRY: 120,
};

app.listen(8080);

console.log('JWT Example is now listening on :8080');

This sets all our dependencies and imports our user and token stores. We also declared an object called jwtAttributes. This object contains the claims that will be used for our token, as well as some other attributes like the app secret and header key. At this point, this server will run but will not do anything because we have not implemented any routes or endpoints.

Let us start implementing the /token endpoint.

// AUTH MIDDLEWARE FOR /token ENDPOINT
const auth = function (req, res) {
  const { EXPIRY, ISSUER, SECRET } = jwtAttributes;

  if (req.body) {
    const user = users.validateUser(req.body.name, req.body.password);
    if (user) {
      const expires = moment().add(EXPIRY, 'seconds')
        .valueOf();
      
      const payload = {
        exp: expires,
        iss: ISSUER,
        name: user.name,
        email: user.email, 
      };

      const token = jwt.encode(payload, SECRET);

      tokens.add(token, payload);

      res.json({ token });
    } else {
      res.sendStatus(401);
    }
  } else {
    res.sendStatus(401);
  }
};

app.post('/token', auth, (req, res) => {
  res.send('token');
});

Before we set up our route for the /token endpoint, we created the authentication middleware. It will check if the request has a body and it will try to validate if a user with the matching password is found on our user store. This middleware could make use of more validation, but I am keeping it simple to make our example less cluttered.

If a user is found, it sets the token's expiry with the help of moment and the set amount of time defined in our jwtAttributes object. Next, we proceed in constructing our payload. Notice that we have two registered claims exp and iss, which stands for expiry and issuer, and two public claims which are the user's name and email.

Finally, the encode method of the jwt-simple package abstracts the process of encoding our payload. It generates our token by concatenating the header and hashing them with the app secret. If the request's body is invalid or if the user/password combo is not found on our store, we return a 401 Unauthorized response. The same goes for sending blank requests, too.

Time for the /secretInfo endpoint.

// VALIDATE MIDDLEWARE FOR /secretInfo
const validate = function (req, res, next) {
  const { HEADER, SECRET } = jwtAttributes;

  const token = req.headers[HEADER];

  if (!token) {
    res.statusMessage = 'Unauthorized: Token not found';
    res.sendStatus('401').end();
  } else {
    try {
      const decodedToken = jwt.decode(token, SECRET);
    } catch(e) {
      res.statusMessage = 'Unauthorized: Invalid token';
      res.sendStatus('401');
      return;
    }
    
    if (!tokens.isValid(token)) {
      res.statusMessage = 'Unauthorized : Token is either invalid or expired';
      res.sendStatus('401');
      return;
    }
    next(); 
  }
};

app.get('/secretInfo', validate, (req, res) => {
  res.send('The secret of life is 42.');
});

Similar to our /token endpoint, we start by implementing our validate middleware. It checks if a token exists in the header, then jwt-simple decodes the token. It gets validated through our token store's method. If the token is found and is not yet expired, we call on the next handler, and the secret message is sent. Otherwise, we send our 401 Unauthorized as the response.

Now that we have finished implementing both endpoints, we can proceed in testing them with Postman.

Testing our app with Postman

Postman is a nifty Chrome app that can be used to test REST APIs. You can get Postman here.

If we send a GET request directly to /secretInfo, we will get a status code of 401, along with an Unauthorized message:

Likewise, sending an incorrect user credentials will give us the same response:

Providing the /token endpoint with a valid payload (a valid JSON with correct user credentials) will provide us a token that is bound to expire in two minutes:

We can then use the token by sending another GET request to /secretInfoendpoint, by including the token through the x-jc-token header (we specified this key on the jwtAttributes object):

Wrap up

That's it! We have successfully implemented a basic token-based authentication on Express by using jwt-simple. Equipped with this knowledge, we can now understand how popular authentication packages uses JWT under the hood. That makes us more capable to troubleshoot JWT authentication problems or even contribute to these packages. If you want to clone the files in this mini-tutorial, you can get them on this Github repository. If you are interested in learning more about JWT, you can get a free eBook here.


Basic Generators in JavaScript

I have been watching a movie last night when my mind spun on a different thread and remembered a JavaScript language feature that have existed for some time now, but I have never had the chance to use. At least, directly.

We do bleeding edge JavaScript at the office. That means we have all these new language features at our disposal as early as possible through the use of Babel. We write JavaScript code using the newest language specification (ECMAScript 6/7) and our code gets transpiled into ECMAScript 5. We have been using all the nifty features such as importasync/awaitspread/rest operators and destructuring as early as last year. These are just the new ES6 features that I can think of off the top, maybe because they are the most practical ones.

There is one feature, however, that can be really powerful but I have not really been able to leverage. They are generators. Prior to V8 v5.5 and Node v7.6.0, Babel's async/await and other asynchronous libraries around has been using generatorsunder the hood to implement this feature.

But what are generators? According to the venerable MDN page:

A generator is a special type of function that works as a factory for iterators. A function becomes a generator if it contains one or more yield expressions and if it uses the function* syntax.

MDN's definition is clear and straightforward, but let me rephrase it from what I have understood. Aside from producing iterables, think of a generator as a function that you can play and pause. This characteristic enables it to implement asynchronous programming, and when used with promises, you can come up with all sorts of things- including your own async library if you want to make one for learning purposes.

Let's dig into some basic code examples to solidify our understanding of generators:

function* counter() {
  for (let i = 0; i < 5; i++) {
    yield i
  }
}

This function was declared using function* and has a yield inside the function body, so this must be a generator. When we invoke it and assign the result to a variable like so, let c = counter(), we get back an iterable object that we can use to iterate over the values of i. An iterable object in JavaScript must have a next()method. This method returns an object that contains a value and a done property. Let's see that in action:

/***************************************************
  Using next() to step through the values explicitly
****************************************************/
let c1 = counter();

console.log(c1.next().value);
// 1
console.log(c1.next().value);
// 2
console.log(c1.next().value);
// 3
console.log(c1.next().value);
// 4
console.log(c1.next().value);
// 5

/***************************************************
  Using a for-of loop
****************************************************/
let c2 = counter();

for (const num of c) {
  console.log(c);
}

// 1
// 2
// 3
// 4
// 5

/***************************************************
  Using the done property explicitly
****************************************************/
let c3 = counter();

let i = c3.next();

while (!i.done) {
  console.log(i.value);
  i = c3.next();
}

// 1
// 2
// 3
// 4
// 5

We went through three different ways on how to iterate over the iterable that was returned by our counter generator. On the first example, we manually stepped through the iterator by using next(). We know that next() returns an object with a valueand a done property, and so we were able to chain .value every time we log the iteration to the console. This shows us one of the concepts that we have discussed earlier: we were able to play and pause the generator's execution by using the next() method. Another interesting thing is that it remembers its internal statethrough its iterations.

It works this way: the generator function stops immediately at every yield statement, and passes the value on its right to the object being returned by next(). We used a loop on our example, and by doing so, the loop gets suspended every time it encounters a yield statement.

Another thing worth knowing is that we can alter the generator's internal state from outside the generator by passing in an argument to next():

function* counter (limit) {
  for (let i = 1; i <= limit; i++) {
    let j = yield i;
    if (j) limit = j;
  }
}

/***************************************************
  Passing a value to next() to alter internal state
****************************************************/
const c1 = counter(2)

console.log(c1.next().value); // 1
console.log(c1.next().value); // 2
console.log(c1.next().value); // undefined

/***************************************************
  Passing a value to next() to alter internal state
****************************************************/
const a2 = counter(2)

console.log(c2.next().value); // 1
console.log(c2.next().value); // 2
console.log(c2.next(5).value); // 3
console.log(c2.next().value); // 4
console.log(c2.next().value); // 5

The example above is yet another contrived modification to our earlier example. This counter generator accepts an argument as the limit to the number of values it can generate. It has the same loop as the above example, except that the control is now dependent on the limit parameter that was passed to it.

Inside the loop body, we have declared a variable j that is being assigned to the value of yield. This expression is being followed by another control structure: an if statement that checks the value of j. The value of j will replace the value of limit if it has a truthy value.

As I have mentioned prior to showing the examples, we can control the internal state of generators by passing an argument to the next() method. This argument will become the value of yield inside the generator, and as such we can assign it to control its behavior.

This can be seen above where we both declared a generator with an initial limit of 2 values. On the first one, we did not pass an argument to next() and so we were only able to iterate through two values. On the second example, we did the same thing, but we passed in a value of 5 as an argument to next(). This altered the generator's internal limit from two to five values, enabling us to get three more values out of it.



On this post, we have learned about the basics of ES6's generators. We went through the basic implementation and usage through some simple examples. We found out that generator functions are declared using the function* keyword, and contains at least one yield statement/expression. We also found out that a generator produces and iterable with a next() method. Since this post is getting long, I have decided to split this post into two. On my next post, we will explore how to implement basic async/await functionality through the use of generators and promises.

Basic OOP and Composition in Go

I have been studying the Go programming language for several weeks now and thought about writing a series of posts to share what I have learned so far. I figured that it will be an excellent way to reinforce my understanding of the language. I initially thought about writing a post that will discuss concurrency in Go but it turned out that I am not yet eloquent enough to talk about basic concurrency patterns with goroutines and channels. I decided to set the draft aside and write about something I am more comfortable with at the moment: basic object-oriented patterns and composition in Go.

One of the best things I like about Go is its terseness. It made me realize that being advanced does not necessarily need to be complex. There are only a few reserved words, and just going through some of the basic data structures will enable you to read and comprehend most Go projects at Github. In fact, Go is not an object oriented language in the purest sense. According to the Golang FAQ:

Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. The concept of “interface” in Go provides a different approach that we believe is easy to use and in some ways more general. There are also ways to embed types in other types to provide something analogous—but not identical—to subclassing. Moreover, methods in Go are more general than in C++ or Java: they can be defined for any sort of data, even built-in types such as plain, “unboxed” integers. They are not restricted to structs (classes).

If Go is not an object-oriented language and everyone is going crazy about Functional Programming in the web development world, then why bother learning OOP patterns in Go? Well, OOP is a widely taught paradigm in CS and IT curricula around the world. If used correctly, I still believe that object-oriented patterns still have its place in modern software development.

Using structs

Go does not have a class similar to a real object-oriented language. However, you can mimic a class by using a struct and then attaching functions to it. The types defined inside the struct will act as the member variables, and the functions will serve as the methods:

package main

import "fmt"

type person struct {
  name string
  age  int
}

func (p person) talk() {
  fmt.Printf("Hi, my name is %s and I am %d years old.\n", p.name, p.age)
}

func main() {
  p1 := person{"John Crisostomo", 25}
  p1.talk()
  // prints: "Hi, my name is John Crisostomo and I am 25 years old."
}

On our example above, we have declared a type struct called person with two fields: name and age. In Go, structs are just that, a typed collection of fields that are useful for grouping together related data.

After the struct declaration, we declared a function called talk. The first parenthesis after the keyword func specifies the receiver of the function. By using pof type person as our receiver, every variable of type person will now have a talkmethod attached to it.

We saw that in action on our main function where we declared and assigned p1to be of type person and then invoking the talk method.

Overriding methods and method promotion

struct is a type, hence, it can be embedded inside another struct. If the embedded struct is a receiver of a function, this function gets promoted and can be directly accessed by the outer struct:

package main

import (
	"fmt"
)

type creature struct {}

func (c creature) walk() {
  fmt.Println("The creature is walking.")
}

type human struct {
  creature
}

func main() {
  h := human{
    creature{},
  }
  h.walk()
  // prints: "The creature is walking."
}

We can override this function by attaching a similarly named function to our human struct:

package main

import (
	"fmt"
)

type creature struct {}

func (c creature) walk() {
  fmt.Println("The creature is walking.")
}

type human struct {
  creature
}

func (h human) walk() {
  fmt.Println("The human is walking.")
}

func main() {
  h := human{
    creature{},
  }
  h.walk()
  // prints: "The human is walking."
  h.creature.walk()
  // prints: "The creature is walking."
}

As we can see on our contrived example, the promoted method can easily be overridden, and the overridden function of the embedded struct is still accessible.

Interfaces and Polymorphism

Interfaces in Go are used to define a type's behavior. It is a collection of methods that a particular type can do. Here's the simplest explanation I can muster: if a struct has all of the methods in an interface, then it can be said that the struct is implementing that interface. This is a concept that can be easily grasped through code, so let us make use of our previous example to demonstrate this:

package main

import (
	"fmt"
)

type lifeForm interface {
   walk()
}

type creature struct {}

func (c creature) walk() {
  fmt.Println("The creature is walking.")
}

type human struct {
  creature
}

func (h human) walk() {
  fmt.Println("The human is walking.")
}

func performAction(lf lifeForm) {
  lf.walk()
}

func main() {
  c := creature{}
  h := human{
    creature{},
  }

  performAction(c)
  // prints: "The creature is walking."
  performAction(h)
  // prints: "The human is walking."
}

In this modified example, we declared an interface called lifeForm which has a walk method. Just like what we have discussed above, it can be said that both creature and human implements the interface lifeForm because they both have a walk method attached to them.

We also declared a new function called performAction, which takes a parameter of type lifeForm. Since both c and h implements lifeForm, they can both be passed as an argument to performAction. The correct walk function will invoked accordingly.

Wrap up

There is so much more to object-oriented programming than what we have covered here but I hope it is enough to get you started in implementing class-like behavior with Golang's structs and interfaces. On my next post, I will talk about goroutineschannels and some basic concurrency patterns in Go. If there's something you would like to add up to what I have covered here, please feel free to leave a comment.