JSON Web Token Authentication With Node.js

JSON Web Token Authentication With Node

Let’s now protect some endpoints by making use of JSON Web Tokens. What are JWTs? JSON web tokens are base64url encoded JSON Objects which are encrypted by the use of a private key. Embedded within the JWT can be one or more sets of name and value pairs. You might have things like a user id or user name embedded within the token. You can not see this data thanks to the encryption in place, but it can be deciphered on the server since the private key is available to the application. JWT.io has a great introduction if you would like all the details. For now, let’s see how we can use JSON web tokens to protect various endpoints in our Node API.

Using Authorization Middleware

In the route and model that we just set up for Platforms of video game systems, we are allowing any user to send a post or put request to the api which modifies data on the server. In fact, pretty much all operations except a simple GET request should have some type of protection. Let’s set that up now.

1. Add a middleware directory

First up, we can add a middleware directory to hold the authorization middleware that we will be using.
middleware directory node app

2. Create an auth.js file

We are creating a new auth.js file to store the logic to read request headers so that this can be used across any endpoint we like.
new authjs middleware file

3. Add code to read and verify JWT

In this auth.js file we complete a few steps. First, we require the json web token and config packages. Then we set up a function which is exported so we can use elsewhere as we like. Lastly, we make sure the logic is in place to read the token, and either grant or deny access based on the provided token. Note the use of the jwt.verify() function which does the heavy lifting for us.


const jwt = require('jsonwebtoken');
const config = require('config');

module.exports = function (req, res, next) {

    const token = req.header('x-auth-token');
    if (!token) {
        return res.status(401).send('Access denied. No JWT provided.');

    try {
        const decoded = jwt.verify(token, config.get('PrivateKey'));
        req.user = decoded;
    catch (ex) {
        res.status(400).send('Invalid JWT.');

Protecting Routes With our new Middleware

Ok we created the middleware, now let’s use it! This is quite easy. To start, we are going to apply the auth middleware to the POST route in the platforms.js routes file. All we have to do is require the new auth middleware, then use it as the second argument to the router.post() function.
require auth middleware and apply to route

Test Auth Middleware Using Postman

Looks like everything is in place, let’s send a POST request to http://localhost:4000/api/platforms without providing any token.
no token post request

So far so good, we are getting the error of “Access denied. No JWT provided.”

Now, we can send a JSON Web Token, but it is a bogus token. Just something silly we make up.
invalid json web token in post request

Now we want to make a POST request using a valid JWT. So first we need to find a JWT to use. We can do this by inspecting the response headers generated by the http://localhost:4000/api/users/ endpoint. Now check this out. Before we use this in our test, let’s see how to decode the JWT. You can visit https://jwt.io/ and paste in the token in question. Then, you can also paste in your own private key. In our case, we simply called it PrivateKey. With this, we can verify the token and also see anything embedded within the token.
decode json web token at jwtio

This shows us that the user id of 5b3b8c70eb573812189785fe is embedded in the token. Now who in the database has that user id? That’s right! Mr Momo!
objectid found in jwt
That means Mr Momo is a valid user, and he should be able to make a POST request now with no problem. We like Mr Momo.

Ok for this last test, we need to do a couple of things. First off, we need to include the JSON Web Token in the POST request we send to the api. How to do that? Simple, just populate the x-auth-token field in Postman.
x-auth-token post request

Now, since we are posting to http://localhost:4000/api/platforms, we recall that this is going to create a new Platform on the server. We will create the “Android” platform like so.
json application data in body

Now for the moment of truth! Send that POST request using both the JWT and the JSON payload to create a new platform.
successful post request using JWT

We got a response back with the JSON object specifying “Android”. What does this mean? It means it worked! Don’t believe me? Let’s also look in Compass.
new insert into mongodb worked

Apply auth Middleware as you see fit

Here is the great thing. We got this middleware working, and applied it to one specific route or endpoint.

Recall it was as easy as using a require to pull in the middleware, like so:

const auth = require('../middleware/auth');

Then, we can use it as the second argument to the router.post() function like so.

router.post('/', auth, async (req, res) => {}

This means you can now use it anywhere you like. For example, no user should be able to delete a platform without being authenticated. Want to add protection to that route? Simple.

router.delete('/:id', auth, async (req, res) => {
    const platform = await Platform.findByIdAndRemove(req.params.id);

    if (!platform) {
        return res.status(404).send('That platform ID was not found');


JSON Web Token Authentication With Node.js Summary

With that, we can see how it is pretty straight forward to implement a middleware to protect various routes by making use of JSON Web Tokens. If a user then tries to make a request without sending a token, the api should respond with a 401 status code indicating unauthorized. If the user does provide a valid token, but does not have the correct privileges, the api can respond with a 403 status code indicating forbidden. Also, do not store the JWT in plain text in the database. It is better for the client to store the JWT. In this tutorial, the JWT was simply stored on the Postman application for testing. Postman itself was acting as the client. In a real application, there would be some type of client built in whatever framework chosen, and the JWT could be stored there.