This content originally appeared on Bits and Pieces - Medium and was authored by Chiboy
A tutorial on using JSON Web Tokens (JWT) for authentication.
Welcome to this tutorial on how to use JSON Web Tokens (JWT) for authentication. JWT is a popular method for securing web applications, APIs, and mobile applications. In this tutorial, we will learn how to use JWT for authentication.
Before we dive deep into the coding section, let's get to know what JWT and Authentication really are.
Jason web token(JWT): This is an open standard (RFC 7519) that defines a compact, self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Authentication: In Node.js, authentication refers to the process of verifying the identity of a user or a system. It is an essential aspect of building secure web applications that require access control. Authentication is often implemented by requiring users to provide some form of identification, such as a username and password, before they can access certain resources or perform certain actions.
In normal human language, for example, let’s say you register for a gym membership. Then you are given a unique membership Id that grants you access to the gym. So whenever you come to the gym after registering you only need to use your unique membership Id to gain access to the gym. In authentication, you need to provide some form of identification to prove who you are and gain access to a system or application. This helps ensure security and privacy by preventing unauthorized access.
So, this project is more focused on the backend functionality so we will be using POSTMAN for testing the endpoints.
Okay, let's get started.
- Open cmd or gitbash terminal then copy and paste the command to create a new project/folder.
mkdir myapp
cd myapp
2. Initialize a new Node.js project and follow the prompts to set it up:
npm init -y
3. Install the required modules for this application using the following command:
npm install express body-parser dotenv mongoose bcrypt jsonwebtoken
4. Now you need to create a MongoDB cluster that will contain your database. Follow this youtube tutorial to get it done fast.
5. Create a new file named index.js and add the following code:
require('dotenv').config()
const express = require('express');
const bodyParser = require('body-parser');
const bcrypt = require("bcrypt");
const conDB = require('./config/db');
const jwt = require("jsonwebtoken");
const userModel = require('./userModel');
const app = express();
const port = process.env.PORT || 5000;
// Parse incoming requests with JSON payloads
app.use(bodyParser.json());
// router handlers
app.get('/home', (req, res) => {
res.status(200).json('You are welcome');
})
// Start the server
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
6. Create a folder in the root directory and name it config , inside the config create a new file and name itdb.js This file contains the connection string to the MongoDB database.
Note: To store environment secrets, you should use an “.env” file. Therefore, please create an “.env” file in the root directory of your project.
require('dotenv').config()
const mongoose = require('mongoose');
// Connecting to mongoDB
const url = process.env.MONGODB_URI // mongoDB connection URL save in .env file
const conDB = async() => {
try {
const connectDB = await mongoose.connect(url);
if(connectDB){
console.log("connected to the database");
} else {
console.log(error => error);
}
} catch (error) {
console.log(`Error: ${error.message}`);
}
}
module.exports = conDB;
7. Now you need to call the database module in the index.js file. So your code should look like this:
require('dotenv').config()
const express = require('express');
const bodyParser = require('body-parser');
const bcrypt = require("bcrypt");
const conDB = require('./config/db');
const jwt = require("jsonwebtoken");
const userModel = require('./userModel');
const app = express();
const port = process.env.PORT || 5000;
// Parse incoming requests with JSON payloads
app.use(bodyParser.json());
// Coonect to the database
conDB();
// router handlers
app.get('/home', (req, res) => {
res.status(200).json('You are welcome');
})
// Define a route that registers users to the database
// Start the server
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
NOTE: To run the application use this command node indexin the terminal. Also, you can use POSTMAN to test the GET method route with http://localhost:5000/home
8. Next we need to create a userModel.js file for the Mongoose schema model in the root directory. This Mongoose schema creates the user to be stored in the database.
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
fullname: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
});
const userModel = mongoose.model('User', userSchema);
module.exports = userModel;
9. Next, you’ll add the code below under the get route just under the comment // Define a route that registers users to the database
// Define a route that registers users to the database
app.post('/register', async(req, res) => {
const {fullname, email, password} = req.body
// hash the password
const hashedpassword = await bcrypt.hash(password, 10);
const newUser = new userModel({
fullname,
email,
password: hashedpassword
})
const userCreated = await newUser.save()
if(!userCreated) {
console.log("user cannot be created");
return res.status(500).send("user cannot be created")
} else {
console.log("user has been created to the database");
return res.status(200).send("user has been created to the database")
}
});
// This route handles user login by authenticating the user's email and password
// and generates a JSON Web Token (JWT) for subsequent authentication of protected routes
// login route
NOTE: This route basically takes the JSON parameter from the POST endpoint and saves them in the database. This can be tested on POSTMAN with this endpoint http://localhost:5000/register on a POST method with this sample request:
{
"fullname": "John Doe",
"email": "Johndoe@gmail.com",
"password": "password6666"
}
10. Now that we can create users to the database, next we need to create a login route to Authenticate the users and generate JWT. Add the following code just below the registered route below the comment // login route
NOTE: To generate a JSON Web Token, you need to provide it with a payload, secret and options.
see documentation
app.post('/login', async(req, res) => {
const { email, password } = req.body;
// Find user by email
const user = await userModel.findOne({ email });
if (!user) {
// If the user doesn't exist, return an error
return res.status(401).send('Invalid email or password');
}
// Check if password is correct
const isPasswordCorrect = await bcrypt.compare(password, user.password);
if (!isPasswordCorrect) {
// If the password is incorrect, return an error
return res.status(401).send('Invalid email or password');
}
// If the email and password are correct, create a JWT token
// Secrete Key saved in .env file
const mysecretkey = process.env.SECRET_CODE;
// Payload to generate JWT
const payload = {
fullName: user.fullName,
email: user.email,
password: user.password,
};
// Create a jsonwebtoken that expires in 5 days
const token = jwt.sign(payload, mysecretkey, { expiresIn: '5d' });
// Send the token back to the client
res.status(200).json({
msg: "User is logged in",
token: token
});
});
So from the above code snippet, we are able to authenticate the user email and password from the stored data created in the database. Then after confirming the user we now generate JWT for further Authentication and authorization.
💡 Pro tip: You could consider making this snippet into its own module using an open-source tool like Bit, then independently test, auto-document, publish, and version it. Then it can be imported in any project you need JWT Auth in, with a bit import, and pass it payload, secret, and options each time.
Learn more here:
Extracting and Reusing Pre-existing Components using bit add
11. To test this on POSTMAN use the POST method with this endpoint http://localhost:5000/login and this sample request.
{
"email": "johndoe@gmail.com",
"password": "password6666"
}
If you follow the steps properly you can now authenticate and generate JWT.
12. Now that we can now generate JWT, let's use the JWT for authentication in a GET method route. Before we do this you will need to add the token in the header endpoint of POSTMAN with a key Authorization. See sample below
Authorization: Bearer <token>
13. Next, let's create a simple GET route in the index.js just below the POST route that uses the generated JWT for authentication.
app.get('/protected', async(req, res) => {
const token = req.headers.authorization.split(' ')[1]; // Get token from Authorization header
const mysecretkey = process.env.SECRET_CODE;
try {
// Verify token and decode payload
const decoded = jwt.verify(token, mysecretkey);
// Get user email from payload
const userEmail = decoded.email;
// Find user by email in the database
const user = await userModel.findOne({ email: userEmail });
if (user) {
res.json({ message: `Welcome ${user.fullname}! This is a protected route.` });
} else {
res.status(401).json({ error: 'Invalid token' });
}
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
});
So, basically what the above code does is, it receives a request from the client with a JWT included in the Authorization header, the server then verifies the JWT using the secret key that was used to generate it. If the JWT is valid, the server extracts the user email from the JWT payload and uses it to find the user in the database. In a nutshell, the clients have been granted access to the protected route using the JWT provided by the client.
If you were able to follow the steps as supposed, you should be able to use and understand the concept of authentication with JWT.
Finally, this tutorial is based on my recent experience with implementing jsonwebtoken in a project. If you want to see the actual source code used in this tutorial, it is available for you to access and use here.
Build Apps with reusable components, just like Lego
Bit’s open-source tool help 250,000+ devs to build apps with components.
Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.
Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:
→ Micro-Frontends
→ Design System
→ Code-Sharing and reuse
→ Monorepo
Learn more:
- Creating a Developer Website with Bit components
- How We Build Micro Frontends
- How we Build a Component Design System
- How to reuse React components across your projects
- 5 Ways to Build a React Monorepo
- How to Create a Composable React App with Bit
- How to Reuse and Share React Components in 2023: A Step-by-Step Guide
- 5 Tools for Building React Component Libraries in 2023
How to Use JWT for Authentication and Create a Login System in Node.js and MongoDB was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Bits and Pieces - Medium and was authored by Chiboy
Chiboy | Sciencx (2023-05-30T15:37:00+00:00) How to Use JWT for Authentication and Create a Login System in Node.js and MongoDB. Retrieved from https://www.scien.cx/2023/05/30/how-to-use-jwt-for-authentication-and-create-a-login-system-in-node-js-and-mongodb/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.