How to implement JWT authentication in Express.js app ?
JSON Web Token
A JSON web token(JWT) is JSON Object which is used to securely transfer information over the web(between two parties). It is generally used for authentication systems and can also be used for information exchange.
This is used to transfer data with encryption over the internet also these tokens can be more secured by using an additional signature. These token consists of header JSON and payload JSON along with the optional signature, The each of three remains concatenated with the “.”, Below is the sample example of JSON Web Token.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2MTU0OWIwMTIwMWUyZjMzZWE3NmFkZjYiLCJlbWFpbCI6InNtdHdpbmtsZTQ1MkBnbWFpbC5jb20iLCJpYXQiOjE2MzI5MzQ2NTgsImV4cCI6MTYzMjkzODI1OH0._oHr3REme2pjDDdRliArAeVG_HuimbdM5suTw8HI7uc
Implementation of JWT authentication: JWT is much popular for authentication and authorization via HTTP. These tokens can be used as credentials to grant permission to access server resources.
Why do we need JWT in the authentication: As HTTP requests are stateless, it is a challenging task to know that the current request is related to the past one. For example, After a log-in user has some rights to change its data but at the next request how the server will identify that it is the same user who requests for login earlier. To solve this challenge we use JWT.
In the first step, the server generates a token with some configurations i.e payload, signature, expiry, etc. Next time when any request from the client-side arrives with the authorization header containing the JWT token, the server decodes that token and uses the details, and permits the access accordingly.
Example:- Let’s create a simple server that has the functionality to login and signup.
Step 1: Initialize server & Install JWT Package.
npm init npm install jsonwebtoken
Step 2: Create Route for Tokens
Explanation:-
- We have imported the express, mongoose, and jsonwebtoken in the first line, and also the User model because that would be necessary to interact with the database. In the next line, we have called the express method which returns an app with which we can configure our server. We are using express.json middleware in the starting because so that server can identify the incoming requests as JSON objects.
- After then we have created two routes one for login and the other for signup.
- Inside the Login route, we have extracted the email and password from the request body and then searched for the user in the database if that is found we are proceeding to check whether the provided password matches with an actual password or not.
- Inside the signup route, we have extracted details like name, email, and password to register users in the database, with the save method provided by the mongoose.
Finally, we have created a token with the 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.
Filename: app.js
Javascript
// 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 .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, get 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 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 1 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.
Javascript
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 to accept the token, we have passed the token in the header and finally server is successful to decode the user details.
Conclusion: With this we have successfully implemented the token from creating to decoding. This example of the ‘accessResource‘ route is sufficient to illustrate the working, you can internally use your token in the way you want and can permit the user accordingly. This all means we are successfully able to persist the information of stateless HTTP requests.
Please Login to comment...