Using JWT With Node.js
Youtube Resource: link
Resource: link
A quick review about JWT
JSON Web Token (JWT) is an open standard that defines a compact and self-contained way of securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
Authorization is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single sign-on is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used across different domains.
Components of JWT
- Header
- Payload
- Signature
Therefore, a JWT typically looks like the following-
xxxxx.yyyyy.zzzzz
The first part of a JWT is an encoded string representation of a simple JavaScript object which describes the token along with the hashing algorithm used. The example below illustrates a JWT using HMAC SHA-256.
{
"typ" : "JWT",
"alg" : "HS256"
}
After encoding, the object becomes this string:
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
The second part of the JWT forms the core of the token. It too represents a JavaScript object, which contains a few pieces of information. Some of these fields are required, and some are optional. An example, taken from the draft specification, is shown below.
{
"iss": "joe",
"exp": 1300819380,
"http://example.com/is_root": true
}
This is called a JWT Claims Set. For the purposes of this article, we’re going to ignore the third parameter. The iss
property is short for issuer
, and specifies the person or entity making the request. Typically, this would be the user accessing the API. The exp
field, short for expires
, is used to limit the lifetime of the token. Once encoded, the JSON token looks like this:
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ
The third, and final, part of the JWT is a signature generated based on the header (part one) and the body (part two). The signature for our example JWT is shown below.
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
The resulting complete JWT looks like this:
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
There are a number of additional, optional properties supported in the specification. Among them are iat
representing the time at which the token was issued, nbf
(Not Before) to indicate the token should not be accepted before a certain time, and aud
(audience) to indicate the recipients the token is intended for.
Implementation in Node.js
Now that we’ve seen how JWT based authentication works, let’s implement it using Node.
Creating the HTTP server
Let’s start by initializing the HTTP server with the required routes in the index.js
file. We’ve used express as the server framework:
const express = require("express");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const { signIn, welcome, refresh } = require("./handlers");
const app = express();
app.use(bodyParser.json());
app.use(cookieParser());
app.post("/signin", signIn);
app.get("/welcome", welcome);
app.post("/refresh", refresh);
app.listen(8000);
We can now define the signIn
and welcome
routes.
Handling user sign in
The /signin
route will take the users credentials and log them in. For simplification, we’re storing the users information as an in-memory map in our code:
const users = {
user1: "password1",
user2: "password2",
}
So for now, there are only two valid users in our application: user1
, and user2
. Next, we can write the signIn
HTTP handler in a new file handlers.js
. For this example we are using the jsonwebtoken library to help us create and verify JWT tokens.
📁 You can see code in Code Folder. Here’s the link
If a user logs in with the correct credentials, this handler will then set a cookie on the client side with the JWT value. Once a cookie is set on a client, it is sent along with every request henceforth. Now we can write our welcome handler to handle user specific information.
Handling post authentication routes
Now that all logged in clients have session information stored on their end as cookies, we can use it to:
- Authenticate subsequent user requests
- Get information about the user making the request
Let’s write our
welcome
handler inhandlers.js
to do just that:
📁 You can see code in Code Folder. Here’s the link
Renewing your token
In this example, we have set a short expiry time of five minutes. We should not expect the user to login every five minutes if their token expires. To solve this, we will create another /refresh
route that takes the previous token (which is still valid), and returns a new token with a renewed expiry time.
To minimize misuse of a JWT, the expiry time is usually kept in the order of a few minutes. Typically the client application would refresh the token in the background.
📁 You can see code in Code Folder. Here’s the link
We’ll need to export the handlers at the end of the file:
module.exports = {
signIn,
welcome,
refresh,
};
Running our application
To run this application, run the command:
node ./index
Now, using any HTTP client with support for cookies (like Postman, or your web browser) make a sign-in request with the appropriate credentials:
POST http://localhost:8000/signin
{"username":"user1","password":"password1"}
You can now try hitting the welcome route from the same client to get the welcome message:
GET http://localhost:8000/welcome
Hit the refresh route, and then inspect the clients cookies to see the new value of the token
cookie:
POST http://localhost:8000/refresh