Implementing Authentication and Authorization in MERN App

In this blog, we will have a look at how we can authenticate a user using JSON Web Token aka JWT. JWT is one of the best standards to implement an authentication system in your MERN stack app.

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and 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.

When Should We Use JWT?

➡️ Authorization: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used across different domains.

➡️ Information Exchange: JSON Web Tokens are a good way of securely transmitting information between parties.

What is the JSON Web Token Structure?

In its compact form, JSON Web Tokens consist of three parts separated by dots (.), which are:

✅ Header
✅ Payload
✅ Signature

Therefore, a JWT typically appears as follows:

Xxxxx.yyyyy.zzzzz

Because JWTs can be signed, for example, using public/private key pairs — you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can verify that the content hasn’t been tampered with.

Unlock Your MERN Stack Potential: Hire a Developer Today!

Server-side Implementation

So below I have shared some code snippets with some explanations. Below these code snippets, we will check if the signed-up user doesn’t exist in the database then it will encrypt the password to store in the database and create a user.

After creating the user it will create a JWT token using the ID of the created user and the name of the user. You can use any type of inputted data like email or phone number too. But I will suggest also including the user ID every time to maintain the uniqueness of the token.

1. Creating a JWT

jwt.sign(
{ id: response.user_id, name: response.user_name },
config.get("jwtSecret"),
{ expiresIn: 86400 },
(err, token) => {
if (err) throw err;
res.status(200).json({
expiresIn:1d,
data: response,
token: token,
});
}
);

So as I mentioned earlier, the JWT token accepts 3 parameters. The first parameter is the “sign” method which takes information that needs to be placed in a payload that gets converted into the JWT token.

The second parameter is the secret key used to create the digest.

The third parameter is the option representation. So in this example, I have set the expiration time of the token in seconds.

2. Verify JWT Using Middleware:

const jwt = require("jsonwebtoken");
const config = require("config");

module.exports = function (req, res, next) {
const token = req.header("Authorization");
if (!token) {
return res.status(401).json({
msg: "Authrization denied",
});
}

try {
const decoded = jwt.verify(token, config.get("jwtSecret"));
req.user = decoded;
next();
} catch (err) {
res.status(401).json({
msg: "invalid token",
});
}
};

In the above example, I implemented an Express.js middleware, which checks the presence of the token and validates the token that we have passed.

You can refer to the above example as the basic implementation of middleware, which expects JWT to be passed in the HTTP request headers to check whether it has the required data or not.

As a result of the token verification best practices, we are sending 401 status codes (Unauthorized) if the token is invalid or expired and 400 (Bad Request) if the token is missing in the headers.

Client-side Implementation

So as mentioned in the title above, we will cover the full tech stack required to implement this functionality. On the client side, we will create a React App that interacts with the backend we created above.

1. Create a React App:

npx create-react-app blogapp-fe
cd blogapp-fe
npm start

So if you are new to React.js, the above commands will create a React application named blogapp-fe with a small boiler plate code and start the server.

Related read: A Complete Guide to Build the First React Native App

2. Create Authentication Pages:

Once your server starts running create basic authentication pages for both SignUp and SignIn. And on clicking a button, we will call the respective APIs.

Here I have a shared basic Signup component example where I have added a form with some fields (Name, Email, and Password) and made a mock submit to demonstrate authentication from the front end side.

import React, { useState } from 'react';
const SignupComponent = () =>
{
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

const handleSubmit = async (e) => {
e.preventDefault(); 
// Create a user object with the form data
const user = { name, email, password }; 
try { 
// Make a POST request to the API endpoint 
const response = await fetch('http://localhost:8080/signup', { method: 'POST',
headers: {
'Content-Type': 'application/json',
}, body: JSON.stringify(user) });
// Check if the request was successful if (response.ok)
{ 
const data = await response.json();
console.log('Signup successful:', data);
// Reset form fields 
setName('');
setEmail(''); 
setPassword('');
} else {
console.log('Signup failed:', response.status);
} 
} catch (error) {
console.log('An error occurred:', error); 
} 
};

return ( 
<form onSubmit={handleSubmit}>
<label>
Name: <input type="text" value={name} onChange={(e) => setName(e.target.value)} />
</label>
<br /> 
<label>
Email: <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
</label>
<br />
<label> 
Password: <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} /> 
</label>
<br />
<button type="submit">Sign Up</button>
</form> 
);
};
export default SignupComponent;

Post-signup API calls will be made by the above component to our backend, which will return user details along with an ID and a JWT access token that we will use to authenticate users and authenticate API requests which I will cover below in this blog.

You can store the response access token in your Redux state, context, or browser local storage to access it from any component.

Now in the below snippet, I made a dummy get API call which authenticates using the access token which is passed inside the request headers as Authorization. And if the token is valid it will give the response with a 200 status code.

If it’s not valid or not passed then our auth middleware will throw an error of 401 with an Invalid token error message.

Related read: How To Implement Redux Toolkit With React.js

Server-side Example

app.get('/data', auth, (req, res) => { 
const data = { 
message: 'Data fetched successfully' 
}; 
res.json(data);
});

Here auth is our middleware which needs to be imported.

Client-side Example

const fetchData = async () => {
try {
const response = await fetch('http://localhost:8080/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json', 
'Authorization': 'Bearer YOUR_AUTH_TOKEN' // Replace YOUR_AUTH_TOKEN with t}
});
if (response.ok) {
const data = await response.json();
console.log('Data fetched successfully:', data); 
} else {
console.log('Failed to fetch data:', response.status);
}
} catch (error) { console.log('An error occurred:', error);
} 
};
coma

Conclusion

In conclusion, we’ve explored the server-side implementation of JWTs, including creating and verifying tokens. We’ve also delved into the client-side, creating a React app that interacts with the backend, handling user sign-up and token-based authentication.

By following the examples and best practices outlined in this blog, you can confidently implement MERN applications with robust authentication and authorization systems. JSON Web Tokens are a valuable tool in your security arsenal, enabling you to protect your application and its data effectively.

Keep Reading

Keep Reading

Join us for “Your 24/7 Clinical Knowledge Partner – The AI Companion” Webinar on Wednesday, 30th July 2025 at 11:00 AM EDT

Register Now
  • Service
  • Career
  • Let's create something together!

  • We’re looking for the best. Are you in?