This content originally appeared on DEV Community and was authored by john mbugua
Page Content
- Introduction to JSON Web Token
- What is JSON Web Token
- Why use JSON Web Token
- When You Should Use JSON Web Token
- The Structure of JSON Web Token
- Setting Up JSON Web Token in a Node.js Application
- Using JSON Web Token with a Node.js Application
- Securing Routes with JSON Web Token in a Node.js Application
- Conclusion
Introduction to JSON Web Token
What's up, techies? 👋In this guide, we are going to explore the magic of JSON Web Tokens (JWT) and how they can make your authentication process secured. Buckle up,and get ready to implement robust authentication in your Node.js apps. Let's get started!
What is JSON Web Token
JSON Web Token (JWT) is a compact and self-contained way to securely transmit information between parties as a JSON object. It is an open standard (RFC 7519) that ensures the information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (HMAC) or a public/private key pair (RSA or ECDSA).
Why use JSON Web Token
JWT is stateless, meaning they don't require server-side session storage, making them highly scalable. They provide a secure way to transmit information and can be easily verified. JWT are also versatile, working well for authentication, authorization, and information exchange in web applications.
When You Should Use JSON Web Token
Authorization:
- JWT are ideal for authorization. Once logged in, users can access routes, services, and resources with their JWT. Single Sign-On (SSO) commonly uses JWT due to its small overhead and cross-domain capabilities.
Information Exchange:
- JWT securely transmit information between parties. With digital signatures, you can verify the sender's identity and ensure the content has not been tampered with.
The Structure of JSON Web Token
JWT consists of three parts separated by dots (.):
- Header
- Specifies the token type (JWT) and signing algorithm (e.g., HS256). Encoded in Base64Url.
{
"alg": "HS256",
"typ": "JWT"
}
- Payload
Contains claims about an entity (usually the user). There are three types of claims:
Registered claims: Predefined, optional claims like iss (issuer), exp (expiration), sub (subject), and aud (audience).
Public claims: Custom claims defined in the IANA JWT Registry or as a URI to avoid collisions.
Private claims: Custom claims agreed upon by parties using the token.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
3.Signature
Verifies the token's integrity. Created using the encoded header, encoded payload, a secret, and the specified algorithm.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
The resulting JWT looks like this: xxxxx.yyyyy.zzzzz.
This format is compact and easily used in web environments.
Setting Up JSON Web Token in a Node.js Application
Before we dive into implementing JSON Web Tokens (JWT) in your Node.js application, let's start with the basics, installation. To get started with JWT, you will need to install the jsonwebtoken package. This library will help you create, sign, and verify JWTs in your application.
Installation
First, you need to install the jsonwebtoken package using npm. Run the following command in your Node.js project directory
npm install jsonwebtoken
This will add the jsonwebtoken package to your project's dependencies.
Next Steps
Now that we have JWT installed, we are ready to implement it in our Node.js application. In the next section, we will cover how to use JSON Web Tokens for user authentication, including creating and verifying tokens using instance methods. Stay tuned!
Using JSON Web Token with a Node.js Application
I know this article is not about Mongoose, schemas, and models, but to effectively implement JSON Web Tokens (JWT) in our Node.js application, we will need to touch on these concepts briefly. Let's assume you have already set up your schema logic using Mongoose. For example:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: [true, "Please insert your name"],
minLength: [3, "Your name is too short"],
},
email: {
type: String,
required: [true, "Please insert your email"],
match: [
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
],
unique: true,
},
password: {
type: String,
required: [true, "Please insert password"],
minLength: [8, "Password is less than 8 character"],
},
});
Now, we will focus on creating a JWT using an instance method.
Creating a JSON Web Token Using an Instance Method
To start, we will create an instance method in our Mongoose model that will generate a JWT for a user. This instance method will be defined in the file where we have our model logic based on Mongoose.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const jwt = require("jsonwebtoken");
const UserSchema = new Schema({
// your schema logic code
});
UserSchema.methods.createToken = function () {
return jwt.sign(
{ userId: this._id, userName: this.name },
process.env.SECRET,
{ expiresIn: process.env.JWT_LIFETIME }
);
};
Explanation
- We assume your schema for example my case UserSchema is already defined in your Mongoose model. We add an instance method createToken ** to the UserSchema. This method uses **jwt.sign to create a token with the user's ID and name ** as **payload, a secret key from environment variables, and an expiration time also from environment variables.
This instance method can be called on any user document to generate a JWT, making it easy to handle user authentication in your application.
Integrating JWT with Login and Registration
Now that we have the instance method to create JWTs, let us see how we can use it in the login and registration logic of our Node.js application. Here is how you can integrate the createToken method:
User registration
During user registration, once the user is successfully created, we can generate a JWT and send it back to the client.
const UserModel = require("../models/User");
const { StatusCodes } = require("http-status-codes");
const { BadRequestError, UnauthenticatedError } = require("../errors");
const register = async (req, res) => {
const { name, email, password } = req.body;
// Create a new user
const user = await UserModel.create({ ...req.body });
// Generate a JWT
const token = user.createToken();
// Respond with the user name and token
res.status(StatusCodes.CREATED).json({ user: { name: user.getName() }, token });
};
module.exports = {
register,
};
User login
For user login, after validating the user's credentials, we can generate a JWT and send it back to the client.
const UserModel = require("../models/User");
const { StatusCodes } = require("http-status-codes");
const { BadRequestError, UnauthenticatedError } = require("../errors");
const login = async (req, res) => {
const { email, password } = req.body;
// Validate the request
if (!email || !password) {
throw new BadRequestError("Please provide email and password");
}
// Find the user by email
const userLogin = await UserModel.findOne({ email });
// If user is not found
if (!userLogin) {
throw new UnauthenticatedError("Invalid credentials");
}
// Check if the password is correct
const isPasswordCorrect = await userLogin.comparePassword(password);
// If the password is incorrect
if (!isPasswordCorrect) {
throw new UnauthenticatedError("Invalid credentials");
}
// Generate a JWT
const token = userLogin.createToken();
// Respond with the user name and token
res.status(StatusCodes.OK).json({ user: { name: userLogin.getName() }, token });
};
module.exports = {
login,
};
In these examples, after a user registers or logs in successfully, we generate a JWT using the createToken instance method and send it back in the response. This token can then be used by the client to authenticate subsequent requests.
Next Steps
With the instance method in place and integrated into your login and registration logic, you can now secure your routes and verify tokens in your Node.js application. In the following section, we will cover how to use this token for securing routes. Stay tuned!
Securing Routes with JSON Web Token in a Node.js Application
With our JWT creation logic in place, the next step is to secure our routes. To do this, we will create a file to store our authentication logic and use it as middleware in our application.
Creating Middleware for Securing Routes
We will create a middleware function that will verify the JWT in incoming requests. This middleware will check the authorization header, verify the token, and attach the user information to the request object if the token is valid.
const UserModel = require("../models/User");
const jwt = require("jsonwebtoken");
const { UnauthenticatedError } = require("../errors");
const auth = async (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
throw new UnauthenticatedError("Authentication invalid");
}
const token = authHeader.split(" ")[1];
try {
const payload = jwt.verify(token, process.env.SECRET);
req.user = { userId: payload.userId };
next();
} catch (err) {
console.log(err);
throw new UnauthenticatedError("Authentication invalid");
}
};
module.exports = auth;
Using the Middleware
Now that we have our authentication middleware, we can use it to secure our routes in various ways. Here are three different ways to apply the middleware:
1. Applying Middleware to Specific Routes
const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const { getUserInfo } = require('../controllers/userController');
router.get('/user-info', auth, getUserInfo);
module.exports = router;
2. Applying Middleware to All Routes in a Router
const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const { getUserInfo, getJobs } = require('../controllers/userController');
router.use(auth);
router.get('/user-info', getUserInfo);
router.get('/jobs', getJobs);
module.exports = router;
3. Applying Middleware in the Main File
const express = require('express');
const app = express();
const auth = require('./middleware/auth');
const jobRoutes = require('./routes/jobRoutes');
app.use("/api/v1/jobs", auth, jobRoutes);
Conclusion
In this article, we covered the basics of JSON Web Tokens (JWT) and how to use them in a Node.js application. We discussed what JWT is, why and when to use it, and how to implement it for user authentication. We also looked at securing routes using middleware in different ways. With these steps, you can enhance the security of your Node.js applications by ensuring only authenticated users can access protected resources.
For more detailed information on JSON Web Tokens, you can visit the jsonwebtoken documentation.
This content originally appeared on DEV Community and was authored by john mbugua
john mbugua | Sciencx (2024-07-05T04:52:53+00:00) Implementing JWT Authentication in Node.js. Retrieved from https://www.scien.cx/2024/07/05/implementing-jwt-authentication-in-node-js/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.