Introduction to Authentication and JWT
Authentication simply is the process of validating a user or an entity attempting to access a resource. It can be perceived as an act of confirmation to see if the said user or entity is who they claim to be before granting access to protected data, information or functionalities.
Authentication can be illustrated using a simple example: before using a mobile device, you are required to unlock it with methods like face ID, password, or PIN before accessing any resources. If you enter an incorrect password or PIN, you are denied access to the device's content. This process of verifying your identity is known as authentication.
JWT(JSON Web Token) is an open standard(commonly accepted specification) that defines a compact and self-contained way to securely transmit information between parties as a JSON object. It consists of three parts: a header, a payload and a signature.
Picture this: You've got a super top-secret message that you need to send to your friends. But here's the catch: you can't let anyone else read or mess with it along the way. So, what's the solution? Put it in the JWT, aka the "super-duper secret envelope of awesomeness!"
Now, let's break it down. This incredible envelope has three major components:
The Header: Think of it as the envelope's fancy label. It shouts out loud, "Hey, world! This is a JWT, and it's locked with an epic secret code!"
The Payload: Inside the envelope lies the juicy stuff—your actual message! It can contain anything you want to share, from your name to your favourite ice cream flavour (super important, obviously).
The Signature: This is where the magic happens. It's like a mind-blowing lock on the envelope, created using a secret key that only you and your friends possess. This lock guarantees that no sneaky intruder can open the envelope or alter your message without the right key (Hehe, take that, unwanted meddlers!).
When you send the JWT to your friends, they can look at the label(header) which tells them "Yo! This is a JWT". Then they can read the message(payload) and be sure it hasn't been changed thanks to the lock(signature).
In a nutshell, JWT acts like a secure envelope for your secret message, ensuring it remains safe during its journey from one place to another. This lightweight and reliable mechanism is widely used for authentication in web applications. Its simplicity, scalability, and compatibility have made it a favoured choice for implementing token-based authentication systems that keeps user data protected and maintain the integrity of communication.
Setting up a JWT Node.js Project
Alright, it is time for the fun part, let's dive into setting up a Node.js project. Here is a step-by-step guide to get you started:
Install Node.js: Ah oy! First things first, you need to have Node.js installed on your computer. You can download and install it from the official Node.js website. Choose the LTS(Long-Term Support) version for stability.
Initialize a New Project: Open your terminal or command prompt and create a new folder for your project. Navigate into that folder and run the following command to initialize a new Node.js project.
npm init
This command will prompt you to enter some information about your project, such as the name, version, description etc. You can press "Enter" to use the default values for most of these, or you can provide your own.
Create Project Structure: Now that you have your project initialized, it is time to create the necessary folder structure. You can have something like this(for this simple demonstration):
- your-project-folder |- src |- controllers |- authController.js |- routes |- authRoutes.js |- index.js |- package.json
The
src
folder would contain your application's source code, andindex.js
will be the entry point of your application.Install Dependencies: Remember, first you have to get the ingredients before you can cook a meal and now it is time to get the ingredients needed for this project 🤓. Okay, all we actually need to do is to install
express
,jsonwebtoken
andbcrypt
.npm install express jsonwebtoken bcrypt
Write your code
After getting the ingredients, you put the pot on fire and start cooking but in our case, you get to open your favourite code editor to start coding. We are going to start out with the index.js
file (or any other name you prefer).
Here is my
index.js
file which is the entry point.const express = require('express'); const app = express(); const authRoutes = require('./routes/authRouter') const port = 4000; //Body Parser app.use(express.json()); app.use('/api/auth', authRoutes); app.get('/', (req, res) => { res.send('Hello, World!') }); app.listen(port, () => { console.log(`The fun is at http://localhost:${port}`); })
Create a
authRoutes.js
file inside theroutes
folder:// routes/authRoutes.js const express = require('express'); const router = express.Router(); const { register, login } = require('../controllers/authController'); router.post('/register', register); router.post('/login', login); module.exports = router;
Create a
authController.js
file inside thecontroller
folder:// controllers/authController.js const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); // Replace this with your own secret key for signing the tokens const secretKey = 'your-secret-key'; const users = []; // Replace this with your database exports.register(req, res) => { //Get the username and password from the body of the request const {username, password} = req.body; //Hash the passord const hashedPassword = bcrypt.hashSync(password, 10); //Save user to the database(array) users.push({username, password: hashedPassord}); //Return a "success" message and status code res.status(201).json({msg: "User registered successfully"}); } exports.login(req, res) => { //Get the username and password from the body of the request const {username, password} = req.body; //Find user by username const user = users.find((u)=>{u.username = username}); //If user doesn't exist or password doesn't match, throw an error if(!user || !bcrypt.compareSync(password, user.password)) { return res.status(401).json({msg: 'Invalid Credentials'}); } //Return a JWT token and a "success" message and status code const token = jwt.sign({username}, secretKey, {expiresIn: '1hr'}); res.status(200).json({msg: 'Login succesful', token}); }
Phew 😮💨, I guess I had to move my fingers a bit for that. Well, now it is time to run our app and this is the secret incantation:
node src/index.js
Yay! 🍾 we just created a basic authentication with JWT and it is now up and running. This example provides a minimal implementation for registration and login. And remember that in a real-world scenario, you would store users in a database and handle token validation more securely.
To test the endpoints, you can use tools like Postman or cURL. For example:
To register a user: POST localhost:4000/api/auth/register Body: { "username": "your-username", "password": "your-password" }
To log in: POST localhost:4000/api/auth/login Body: { "username": "your-username", "password": "your-password" }
After a successful login, you'll receive a JWT token that you can use for authenticating subsequent requests to protected routes.