How To Implement JWT Authentication in Express App?
JWT authentication in an Express app involves issuing a token when a user logs in and verifying that token on protected routes. This ensures only authenticated users can access certain resources.
Implementation of JWT
We can implement JWT authentication in the Express app by following the below steps:
Step 1: Initialize the server & Install JWT Package.
npm init
npm install jsonwebtoken
Step 2: Create Route for Tokens
- We've brought in essential libraries - express, mongoose, and JSON web token, including the User model for database interaction. Creating an Express app
express()
allows server configuration. - Using express.json() initially helps recognize incoming requests as JSON. Two routes are set up for login and signup.
- In the login route, we extract the email and password from the request body, searching for the user in the database. If found, we verify the provided password.
- For signup, we extract user details (name, email, password) and use the Mongoose
save
method to register users in the database.
Finally, we have created a token with a 1-hour expiry by providing payload as user id and email because only this is sufficient to extract the user information. The sign method accepts payload, secret jwt key, and expiry time, then generates a token.
// Importing modules
const express = require("express");
const mongoose = require("mongoose");
const jwt = require("jsonwebtoken");
const User = require("./userModel");
const app = express();
app.use(express.json());
// Handling post request
app.post("/login",
async (req, res, next) => {
let { email, password } = req.body;
let existingUser;
try {
existingUser =
await User.findOne({ email: email });
} catch {
const error =
new Error(
"Error! Something went wrong."
);
return next(error);
}
if (!existingUser
|| existingUser.password
!= password) {
const error =
Error(
"Wrong details please check at once"
);
return next(error);
}
let token;
try {
//Creating jwt token
token = jwt.sign(
{
userId: existingUser.id,
email: existingUser.email
},
"secretkeyappearshere",
{ expiresIn: "1h" }
);
} catch (err) {
console.log(err);
const error =
new Error("Error! Something went wrong.");
return next(error);
}
res
.status(200)
.json({
success: true,
data: {
userId: existingUser.id,
email: existingUser.email,
token: token,
},
});
});
// Handling post request
app.post("/signup",
async (req, res, next) => {
const {
name,
email,
password
} = req.body;
const newUser =
User({
name,
email,
password,
});
try {
await newUser.save();
} catch {
const error =
new Error("Error! Something went wrong.");
return next(error);
}
let token;
try {
token = jwt.sign(
{
userId: newUser.id,
email: newUser.email
},
"secretkeyappearshere",
{ expiresIn: "1h" }
);
} catch (err) {
const error =
new Error("Error! Something went wrong.");
return next(error);
}
res
.status(201)
.json({
success: true,
data: {
userId: newUser.id,
email: newUser.email,
token: token
},
});
});
//Connecting to the database
mongoose
.connect("mongodb://localhost:27017/testDB")
.then(() => {
app.listen("3000",
() => {
console.log("Server is listening on port 3000");
});
})
.catch(
(err) => {
console.log("Error Occurred");
}
);
Output
We are testing our API with the Postman, we have provided the data for signup in the request body, and finally, got our token with some other details.
Step 3: Decoding JWT Token
- We can receive our request with a token to grant the permissions, here we are showing a simple example of how a token is being decoded.
- The token is being sent by request header, we are extracting the token here from the authorization header we are using the split function because the token remains in the form of "Bearer Token," and we only want to extract the token, that's why providing the one index.
- The verify method accepts the token and jwt key and provides the decode of the token. After this, we can get the information of the user.
app.get('/accessResource',
(req, res) => {
const token =
req.headers
.authorization.split(' ')[1];
//Authorization: 'Bearer TOKEN'
if (!token) {
res.status(200)
.json(
{
success: false,
message: "Error!Token was not provided."
}
);
}
//Decoding the token
const decodedToken =
jwt.verify(token, "secretkeyappearshere");
res.status(200).json(
{
success: true,
data: {
userId: decodedToken.userId,
email: decodedToken.email
}
}
);
})
Output
Here, we are testing the API which is responsible for accepting the token, we have passed the token in the header and finally, the server is successful in decoding the user details.
Why do we need JWT in the authentication?
JSON Web Tokens (JWTs) are essential in authentication for securely transmitting user identity and permissions in a stateless manner.
- They enable servers to verify and grant access without storing session data, enhancing scalability and efficiency.
- JWTs facilitate seamless user authentication across multiple requests by embedding necessary information within the token.