Beginner's authentication, JWT and cookies

When I first started learning web development, my goal was to make applications that were personal to the user. Static sites with functionality were cool, but what I wanted to build was something that would allow people to have profiles and save data about themselves. This, to me, was the fundamental building block for making meaningful applications.

But for a long time, my journey towards understanding how to do this was stymied by a misconception about what happens when someone logs into a web application.

In this post I'm going to discuss this misconception, as I think it might be helpful to other budding web developers. I'll also share what I've learned about user authentication, and give an introduction to using JSON Web Tokens and cookies, which I'm currently pretty excited about!

Badges not gateways

So, about this misconception...

I had always seen the process of registering with, and logging into an application as like passing through a gateway: you have your username and your password, and these are checked at the gateway to the site. If those credentials are legit, you're in! You pass through the gateway and enter the otherwise restricted area, at which point you can swan around to your heart's content - no one needs to check your credentials again right?

Well actually no it turns out, that's not right at all!

A more accurate analogy is to think of logging in as like being given a special badge that details where you are allowed to go. What's more, once you are given this badge it will be checked every time you go into a new area!

This is the process of continuous authentication that happens when you log into and navigate around a site. You haven't passed a gateway once and for all, rather you are constantly having your credentials checked.

This is no doubt obvious to many readers but for me, as a career changer with limited previous tech experience, understanding this distinction made a lot of things click into place.

Putting this into practice

So now that we've cleared up this misconception, how do we put it into practice? What follows is an outline of what I've learned recently, which should provide a helpful primer for those trying to get to grips with authentication.

I'll say at this point that I'm not a cybersecurity expert this is a map of my journey rather than a list of best practices!

One method for authentication is to assign a user a unique string when they log in, save this in the user's entry on your database, store a copy in the browser's local storage, and then compare the two every time the user accesses a part of the application that requires authentication.

This is a simple approach that I found useful for understanding the concept of authentication, but a little research shows that it's insecure and not a good option for using with your deployed app.

A better option, which is not too tricky to implement and is therefore worth taking the time to learn, is to use JSON Web Tokens (JWTs) and cookies.

JWTs allow you to encode information within a token which can then be decoded when a user navigates to a new page and used to confirm the user is authorised. For instance, a user's ID can be encoded within the JWT (as its payload), which can then be stored as a cookie. At this point the whole thing can be used to check the user and access their information when they move around your application.

What's fab is that JWTs are super easy to use!

I implemented this as part of a MERN application (so I was using MongoDB, Express.js, React (well, Next.js actually), and Node.js).

There are several excellent tutorials out there (I learned by combining the approaches of Code with Yousaf, Web Dev Simplified, Traversy Media, and this article from Francisco Mendes) so this is just a summary, but basically it works as follows.

This is non-exhaustive code to add to your existing MERN application, you'll still need to add everything else like express and corsetc. Here is a link to my repository (branch v1) on GitHub, so you can see it all in context and with the completed code.

Install JWT and cookie-parser with npm:

npm i jsonwebtoken cookie-parser

In your main index.js or app.js file, require cookie-parser (along with all other necessary packages) then app.use it with express. Doing this will give you access to cookie-parser's functionality throughout your application.

const cookieParser = require("cookie-parser")

app.use(cookieParser()) 

In your login route, require jsonwebtoken and cookie-parser, then create the token with the sign method, passing in your payload (e.g. a user's MongoDB _id), secret key (from a separate .env file), and additional options (e.g. an expiration date for the token). Assign the JWT to a variable and bingo, you're most of the way there!

const jwt = require("jsonwebtoken");

const token = jwt.sign({user._id}, process.env.JWT_SECRET_KEY, {
	expiresIn: "30d",
})

Still within your login route, you can add the token as a cookie, using the cookie-parser .cookie method, which takes as arguments a name for the cookie as a key, a value of the cookie (which will be our variable containing the JWT), plus additional options (here we're using httpOnly to further secure our JWT).

return res.cookie("token", token {
	httpOnly: true
})

So far, doing this has set our JWT as a cookie, but next we need to use it to authenticate the user. I did this in a small piece of middleware which gets the token from the cookie:

const token = req.cookies.token

We then use use the .verify method from jsonwebtoken to check its authenticity.

jwt.verify(token, process.env.JWT_SECRET, (err, result)

The result is an object that we can access to find the payload. In our case this was the user _id, to which we gave the key of "id", so we can access it with result.id. This can then be used to confirm which user has accessed the page, thereby authenticating them!

A learning experience

Learning about authentication has been really enjoyable and doing so has really improved my understanding of the web and full stack applications. This post only scratches the surface as far as I can tell and there are other, even more secure methods of authentication (e.g. OAuth), that I'm keen to get a handle on soon.

But for now I wanted to share my learning experience, as well as what I've learned, in the hope that it will help others with their learning, especially those labouring under the "gateway" misconception that had hampered my understanding!

Postscript - please leave feedback!

On a personal note, this is my first vaguely technical article so I'm keen to hear feedback from those with more experience. It was going to be a short piece but has ballooned into something more detailed - this seemed unavoidable as I wrote, and has helped me consolidate my knowledge. But with my relative lack of experience, it raises the question: when is the right time to start writing technical pieces?

AuthenticationExpressMernJwtCookies
Avatar for Max Brookman-Byrne

Written by Max Brookman-Byrne

Self-taught junior web developer, currently honing my MERN skills with a bootcamp at The Developer Academy, Sheffield.

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.