https://auth0.com/blog/jwt-json-webtoken-logo/

Add JWT Authentication to Node.js

In my earlier story I wrote about how to best transfer from clients and how to best store passwords on the server side, you can check it our here, the next step up is to add authentication tokens, and I’m going to explain how to do that with JASON Web Tokens (JWT), also I will be providing the full source code at the end of the story.

The great thing about JWT is that its super simple to understand, implement and there are plenty of libraries for a variety of languages, I even contributed to one of them here and here back in 2015 😎.

Enough with the talking, I’m going to reuse the project used in A safer way to deal with passwords, the code doesn’t look exactly the same as I did a few improvements, anyway, let’s get to it!

The first thing I did was to pick a pre-made JWT library, I went with jsonwebtoken because it was created by Auth0, you can find more libraries at jwt.io, then opened a terminal, went to my node.js projects root and run the following command to download, install and save the new dependency:

npm install jsonwebtoken --save

Next, I imported the module using:

const jwt = require('jsonwebtoken')

Next I added two new URLs to node, /signIn and /update, to sign in and to update the username of the signed in user.

When the website calls /signIn, I query my test mongodb database for valid credentials, once that’s successful I create the JWT token with an expiration of 1 hour, and then I send the token back to the caller as follows:

iat means issues at, exp means expiration and id is a custom id that identifies the user, once I construct the payload I pass it to jwt.sign() to create the token, ok cool, then what’s jwt_secret? this secret is automatically read once my node application starts and it creates it if it doesn’t exist in my secrets file, it’s a base64-encoded cryptic random bytes of 32 bytes long, I create it using crypto.randomBytes(32), modify all this information to fit the needs of your application, the code I created to read/create secrets is below

The secret is needed to sign the JWT to make sure that the content of the JWT is not altered, and if it is, to detect it before trying to do anything with it.

JWT by default doesn’t encrypt, it just base64 encodes the payloads, adds a header and appends the signature to it, there are ways to encrypt JWT but for the purpose of this example we don’t need to do that, and if you’re not encrypting the JWT either make sure you don’t put sensitive information in there.

Ok, cool back on track, once the token is created we send it to the called in a JSON response, the website reads this and stores it in localStorage, for the purpose of this project localStorage is enough, websites can store information using key/value pairs using localStorage and it will persist even if the computer is restarted, JWT claims that there are security issues by storing tokens and sensitive information in localStorage, the default behavior is that localStorage sandboxes/protects the information stored in there only to the host that stored it, so no other website/host has access to this data, but keep in ming that it’s vulnerable to cross-site scripting, same as cookies, ah yes, I didn’t store the token in a cookie because based on mozilla cookies are a thing of the past =)

If anyone has a safer approach on how to store tokens on the client side please let me know! 🙏

So this is how the website requests the signIn and handles the token:

First before anything we securely hash the password, then we send the POST fetch request, once I receive the response, I parse the JSON, read the token and store it in localStorage using localStorage.setItem().

Once the token is stored in localStorage, let’s move to the /update request for changing the user’s username to something else, the HTML form code is very simple, it collects the new username and calls onChangeAccount():

The onChangeAccount() implementation is below:

The first thing we do is to read the token from the localStorage using localStorage.getItem(), the token is later passed in with the Authorization request header with Bearer type as follows: Authorization: Bearer ${token}.

On the server side, before we change any data I validate and extract the payload data, if the JWT is invalid I return an error, otherwise I proceed with the editing by using the id value from the payload to query the user from the database and modify it, for this I create a helper function that returns the payload only if the authorization header exists and the JWT is valid:

and the code that uses the payload is highlighted below:

As you can see in the code above, I get the users collection from the test database, I then update the username for the user with the matching ID.

Well, this was a very simple story, I hope it helps in your endeavors, as always, please feel free to add comments or questions in the section below, or feel free to reach out to me via twitter at @ObjSal.

Don’t stop here, please continue reading and learning about JWT from it’s official website, and play around with its online JWT debugger.
References:

Computer Science Engineer, Cross-Platform App Developer, Open Source contributor. 🇲🇽🇺🇸

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store