Showing posts with label jwt authentication. Show all posts
Showing posts with label jwt authentication. Show all posts

Tuesday, 13 February 2024

Simplifying User Authentication with JWT Tokens in Node.js


In modern web development, user authentication is a fundamental aspect of building secure applications. Implementing a login and registration system using JSON Web Tokens (JWT) in Node.js offers a robust solution that enhances security and simplifies user management. In this article, we'll explore how to implement user authentication using JWT tokens in a Node.js application.


Simplifying User Authentication with JWT Tokens in Node.js

What are JWT Tokens?


JWT tokens are an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. These tokens can be signed using a secret or a public/private key pair, providing a means of verifying the integrity of the information contained within.

  1. Step 1: Setting Up Your Node.js Environment
  2. Step 2: Creating the Express Server
  3. Step 3: Database Connection
  4. Step 4: Setting Up Routes
  5. Step 5: Implementing User Registration
  6. Step 6: Implementing User Login
  7. Step 7: Protecting Routes
  8. Step 8: Run Application
  9. Step 9: Conclusion

Step 1: Setting Up Your Node.js Environment


Ensure you have Node.js installed on your machine. If not, download and install it from the official Node.js website. Once installed, open your terminal and create a new directory for your project.

	
		mkdir node-jwt-auth
		cd node-jwt-auth
	

Initialize a new Node.js project and install the necessary dependencies.

	
		npm install express jsonwebtoken bcrypt body-parser mongoose
	

Step 2: Creating the Express Server


Create a file named app.js and set up a basic Express server.

app.js
	
		const express = require('express');
		const mysql = require('mysql2');
		const bcrypt = require('bcrypt');
		const jwt = require('jsonwebtoken');
		const app = express();
		const port = 3000;
		app.use(express.json());
		//Serve static files (including index.html) from the root directory
		app.use(express.static(__dirname));
	

Step 3: Database Connection


Under this app.js file we have to make MySQL Database connection. So user registration data will be stored under MySQL database.

app.js
	
		const database = mysql.createConnection({
			host : 'localhost',
			user : 'root',
			password : '123456789',
			database : 'testing'
		});

		database.connect((error)=> {
			if(error){
				console.error('Error connecting to MySQL : ', error);
			} else{
				console.log('Connected to MySQL database');
			}
		});
	

It will make database connection and also check that there is any error has been occured during database connection.

Below you can find MySQL table structure for user table. So you have to copy this .sql code and run in local MySQL database. So it will create user under which registration data will be stored.

	
		CREATE TABLE `user` (
		  `user_id` int NOT NULL AUTO_INCREMENT,
		  `user_email` varchar(70) DEFAULT NULL,
		  `user_password` varchar(70) DEFAULT NULL,
		  `user_name` varchar(45) DEFAULT NULL,
		  `email_verification_status` enum('Not Verified','Verified') DEFAULT NULL,
		  PRIMARY KEY (`user_id`)
		) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
	

Step 4: Setting Up Routes


Create routes under app.js file for handling user authentication and registration.

app.js
	
		app.get('/', (request, response)=>{
		
		});
		
		app.post('/register', async (request, response)=>{
		
		});
	

Define routes for user registration, login, and protected resources in the respective files.

Step 5: Implementing User Registration


First we have goes into '/' get route, and under this we have to write following code which will load index.html file on browser.

app.js
	
		app.get('/', (request, response)=>{
			response.sendFile(__dirname + '/index.html');
		});
	

After this, we have goes to index.html file and under this we have to create register form and then after we have to write JavaScript code for submit register form data using JavaScript fetch API. And here we have also use try catch block of handle error at front end side.

index.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Register</div>
								<div class="card-body">
									<form id="registerForm">
										<div class="mb-3">
											<label><b>Name</b></label>
											<input type="text" name="name" id="name" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>eMail</b></label>
											<input type="text" name="email" id="email" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>Password</b></label>
											<input type="password" name="password" id="password" class="form-control" />
										</div>
										<input type="submit" class="btn btn-primary" value="Register" />
									</form>
								</div>
							</div>
						</div>
					</div>
				</div>

				<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
			</body>
		</html>

		<script>

		document.getElementById("registerForm").addEventListener('submit', async function(event){
			event.preventDefault();
			const name = document.getElementById("name").value;
			const email = document.getElementById("email").value;
			const password = document.getElementById("password").value;
			let messageArea = document.getElementById("msgArea");
			try{
				const response = await fetch('/register', {
					method : 'POST',
					headers : {
						'Content-Type': 'application/json'
					},
					body : JSON.stringify({name, email, password})
				});
				if(response.ok){
					messageArea.innerHTML = '<div class="alert alert-success">User registered successfully!</div>';
				} else {
					const data = await response.json();
					messageArea.innerHTML = `<div class="alert alert-info">Error : ${data.error}</div>`;
				}

			} catch(error){
				messageArea.innerHTML = '<div class="alert alert-danger">Internal Server Error</div>';
			}
		});

		</script>
	

Now in app.js, implement the route for user registration. Hash the user's password using bcrypt before storing it in the database and here it has also check email is already exists or not also.

app.js
	
		app.post('/register', async (request, response)=>{
			try{
				const {name, email, password} = request.body;
				if(!name || !email || !password){
					return response.status(400).json({error : 'Please provide all required fields'});
				}
				// Check if the email already exists in the database
				database.query('SELECT * FROM user WHERE user_email = ?', [email], async (error, results) =>{
					if(error){
						return response.status(500).json({error : 'Internal Server Error'});
					}
					if(results.length > 0){
						return response.status(400).json({error : 'Email already exists'});
					}
					const hashedPassword = await bcrypt.hash(password, 10);
					//Insert registeration data
					database.query('INSERT INTO user (user_email, user_password, user_name) VALUES (?, ?, ?)', [email, hashedPassword, name], (error) => {
						if(error){
							console.log(error);
							return response.status(500).json({error : 'Internal Server Error'});
						}
						return response.status(201).json({message : 'User registered successfully'});
					});
				});
			} catch(error){
				response.status(500).json({error : 'Internal Server Error'});
			}
		});
		app.listen(port, () => {
			console.log(`Server is running on http://localhost:${port}`);   
		});
	

Step 6: Implementing User Login


Now for create Login in this Node JS Application, first in app.js file we have go create route for load login form in the browser.

app.js
	
		app.get('/login', (request, response) => {
			response.sendFile(__dirname + '/login.html');
		});
	

So it will send login.html file in browser and display login login form on web page.

Next we have to create login.html file and under this file, we will write HTML code for display Login form and JavaScript code for submit login form data to server.

login.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Login</div>
								<div class="card-body">
									<form id="loginForm">
										<div class="mb-3">
											<label><b>eMail</b></label>
											<input type="text" name="email" id="email" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>Password</b></label>
											<input type="password" name="password" id="password" class="form-control" />
										</div>
										<input type="submit" class="btn btn-primary" value="Login" />
									</form>
								</div>
							</div>
						</div>
					</div>
				</div>

				<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
			</body>
		</html>

		<script>

		document.getElementById('loginForm').addEventListener('submit', async function(event){
			event.preventDefault();
			const email = document.getElementById('email').value;
			const password = document.getElementById('password').value;
			try {
				const response = await fetch('/login', {
					method : 'POST',
					headers : {
						'Content-Type': 'application/json',
					},
					body : JSON.stringify({ email, password })
				});
				const data = await response.json();
				if(response.ok){
					localStorage.setItem('token', data.token);
					window.location.href = '/welcome';
				} else {
					document.getElementById('msgArea').innerHTML = `<div class="alert alert-info">Error : ${data.error}</div>`;
				}
			} catch(error){
				document.getElementById('msgArea').innerHTML = '<div class="alert alert-danger">Internal Server Error</div>';
			}
		});

		</script>
	

Once login form data has been submitted then it will send login data to /login route of app.js file. And under this file it will validate user login data and here it also also compare simple login form password with hashed formatted password which is stored in database by using bcrypt library.

app.js
	
		app.post('/login', async (request, response) => {
			try {
				const {email, password} = request.body;
				if(!email || !password){
					return response.status(400).json({ error : 'Please provide all required fields'});
				}
				database.query('SELECT * FROM user WHERE user_email = ?', [email], async (error, results) => {
					if(results.length > 0){
						const user = results[0];
						if(await bcrypt.compare(password, user.user_password)){
							const token = jwt.sign({ userId : user.user_id }, secretKey, { expiresIn : '1h' });
							response.status(200).json({ token });
						} else {
							response.status(401).json({ error : 'Wrong Password' });
						}
					} else {
						response.status(401).json({ error : 'Wrong Email' });
					}
				});
			} catch(error){
				response.status(500).json({ error : 'Internal Server Error' });
			}
		});
	

Step 7: Protecting Routes


Once we have make login page, when user has been login into system then user data has been stored in JWT token. Now we want to verify that user has been login into system or not. So for this we have to make one middleware to check user is login or not. In middleware it will decode JWT token data and then after it has authenticate that user is login or not.

So for this first we have to create one button, so when we have click on that button then it will send request to Node server route for fetch data from JWT token. So when we have send request to server, then in header it will send encoded JWT token data.

welcome.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Welcome Page</div>
								<div class="card-body">
									<h1 class="text-center">Welcome User</h1>
									<p class="text-center">
										<button type="button" class="btn btn-warning" onclick="getJWTData()">Get User ID</button>
										<button type="button" onclick="logout()" class="btn btn-primary">Logout</button>
									</p>
								</div>
							</div>
						</div>
					</div>
				</div>

				<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
			</body>
		</html>

		<script>

		const token = localStorage.getItem('token');
		if(!token){
			window.location.href = '/login';
		}

		function logout(){
			localStorage.removeItem('token');
			window.location.href = '/login';
		}

		function getJWTData(){
			fetch('/getJWTData', {
				headers : {
					'Authorization' : token
				}
			})
			.then(response => {
				return response.json();
			})
			.then(data => {
				alert(`Login User ID is - ${data.userId}`);
			})
			.catch(error => {
				alert(error);
			});
		}

		</script>
	

Now at Node backend side code, we have to create getJWTData route and under this route we have to add verifyToken middleware. So this middleware code will be first executed and it will first receive JWT token data from HTTP header. And then after by using JWT library it will again decode that data. If data has been successfully decoded that it will execute other part of code. But Suppose there JWT token not found in HTTP headers then it will directly send error to client without executing next code. But suppose data has been decoded from JWT token then it will send back that data to client which will be pop up on web page. So this way it will fetch data from JWT token under Node JS application.

app.js
	
		// Middleware to check JWT token
		function verifyToken(request, response, next){
			const token = request.headers.authorization;
			if(!token){
				return response.status(401).json({ error : 'Access denied. No token provided.'});
			}
			try {
				const decoded = jwt.verify(token, secretKey);
				request.user = decoded;
				next();
			} catch(error){
				response.status(401).json({ error : 'Invalid token' });
			}
		}

		app.get('/getJWTData', verifyToken, (request, response) => {
			response.status(200).json({ userId : request.user.userId });
		});
	

Step 8: Run Application


Once our code is ready, now for check output in browser, we have goes to terminal and run node app.js command which will start node server.

And in browser we can open this Node application by open http://localhost:3000 this url.

Step 9: Conclusion


You've successfully implemented a login and registration system using JWT tokens in your Node.js application. This provides a secure way to manage user sessions and protect sensitive resources. With the flexibility of Node.js and the simplicity of JWT tokens, you can now build robust authentication systems for your web applications.

Complete Source Code


app.js
	
		const express = require('express');
		const mysql = require('mysql2');
		const bcrypt = require('bcrypt');
		const jwt = require('jsonwebtoken');
		const app = express();
		const port = 3000;
		app.use(express.json());
		//Serve static files (including index.html) from the root directory
		app.use(express.static(__dirname));
		const database = mysql.createConnection({
			host : 'localhost',
			user : 'root',
			password : '123456789',
			database : 'testing'
		});

		database.connect((error)=> {
			if(error){
				console.error('Error connecting to MySQL : ', error);
			} else{
				console.log('Connected to MySQL database');
			}
		});

		const secretKey = 'eyJhbGciOiJIUzI1NiJ9.eyJSb2xlIjoiQWRtaW4iLCJJc3N1ZXIiOiJJc3N1ZXIiLCJVc2VybmFtZSI6IkphdmFJblVzZSIsImV4cCI6MTcwNjg3ODE1MywiaWF0IjoxNzA2ODc4MTUzfQ.i4j208HUwM7JjLJL98o9EkE68Ia87i694iq7r67zRHM';

		app.get('/', (request, response)=>{
			response.sendFile(__dirname + '/index.html');
		});

		app.post('/register', async (request, response)=>{
			try{
				const {name, email, password} = request.body;
				if(!name || !email || !password){
					return response.status(400).json({error : 'Please provide all required fields'});
				}
				// Check if the email already exists in the database
				database.query('SELECT * FROM user WHERE user_email = ?', [email], async (error, results) =>{
					if(error){
						return response.status(500).json({error : 'Internal Server Error'});
					}
					if(results.length > 0){
						return response.status(400).json({error : 'Email already exists'});
					}
					const hashedPassword = await bcrypt.hash(password, 10);
					//Insert registeration data
					database.query('INSERT INTO user (user_email, user_password, user_name) VALUES (?, ?, ?)', [email, hashedPassword, name], (error) => {
						if(error){
							console.log(error);
							return response.status(500).json({error : 'Internal Server Error'});
						}
						return response.status(201).json({message : 'User registered successfully'});
					});
				});
			} catch(error){
				response.status(500).json({error : 'Internal Server Error'});
			}
		});

		app.get('/login', (request, response) => {
			response.sendFile(__dirname + '/login.html');
		});

		app.post('/login', async (request, response) => {
			try {
				const {email, password} = request.body;
				if(!email || !password){
					return response.status(400).json({ error : 'Please provide all required fields'});
				}
				database.query('SELECT * FROM user WHERE user_email = ?', [email], async (error, results) => {
					if(results.length > 0){
						const user = results[0];
						if(await bcrypt.compare(password, user.user_password)){
							const token = jwt.sign({ userId : user.user_id }, secretKey, { expiresIn : '1h' });
							response.status(200).json({ token });
						} else {
							response.status(401).json({ error : 'Wrong Password' });
						}
					} else {
						response.status(401).json({ error : 'Wrong Email' });
					}
				});
			} catch(error){
				response.status(500).json({ error : 'Internal Server Error' });
			}
		});

		app.get('/welcome', (request, response) => {
			response.sendFile(__dirname + '/welcome.html');
		});

		// Middleware to check JWT token
		function verifyToken(request, response, next){
			const token = request.headers.authorization;
			if(!token){
				return response.status(401).json({ error : 'Access denied. No token provided.'});
			}
			try {
				const decoded = jwt.verify(token, secretKey);
				request.user = decoded;
				next();
			} catch(error){
				response.status(401).json({ error : 'Invalid token' });
			}
		}

		app.get('/getJWTData', verifyToken, (request, response) => {
			response.status(200).json({ userId : request.user.userId });
		});


		app.listen(port, () => {
			console.log(`Server is running on http://localhost:${port}`);   
		});
	

index.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Register</div>
								<div class="card-body">
									<form id="registerForm">
										<div class="mb-3">
											<label><b>Name</b></label>
											<input type="text" name="name" id="name" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>eMail</b></label>
											<input type="text" name="email" id="email" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>Password</b></label>
											<input type="password" name="password" id="password" class="form-control" />
										</div>
										<input type="submit" class="btn btn-primary" value="Register" />
									</form>
								</div>
							</div>
						</div>
					</div>
				</div>

				<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
			</body>
		</html>

		<script>

		document.getElementById("registerForm").addEventListener('submit', async function(event){
			event.preventDefault();
			const name = document.getElementById("name").value;
			const email = document.getElementById("email").value;
			const password = document.getElementById("password").value;
			let messageArea = document.getElementById("msgArea");
			try{
				const response = await fetch('/register', {
					method : 'POST',
					headers : {
						'Content-Type': 'application/json'
					},
					body : JSON.stringify({name, email, password})
				});
				if(response.ok){
					messageArea.innerHTML = '<div class="alert alert-success">User registered successfully!</div>';
				} else {
					const data = await response.json();
					messageArea.innerHTML = `<div class="alert alert-info">Error : ${data.error}</div>`;
				}

			} catch(error){
				messageArea.innerHTML = '<div class="alert alert-danger">Internal Server Error</div>';
			}
		});

		</script>
	

login.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Login</div>
								<div class="card-body">
									<form id="loginForm">
										<div class="mb-3">
											<label><b>eMail</b></label>
											<input type="text" name="email" id="email" class="form-control" />
										</div>
										<div class="mb-3">
											<label><b>Password</b></label>
											<input type="password" name="password" id="password" class="form-control" />
										</div>
										<input type="submit" class="btn btn-primary" value="Login" />
									</form>
								</div>
							</div>
						</div>
					</div>
				</div>

				<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
			</body>
		</html>

		<script>

		document.getElementById('loginForm').addEventListener('submit', async function(event){
			event.preventDefault();
			const email = document.getElementById('email').value;
			const password = document.getElementById('password').value;
			try {
				const response = await fetch('/login', {
					method : 'POST',
					headers : {
						'Content-Type': 'application/json',
					},
					body : JSON.stringify({ email, password })
				});
				const data = await response.json();
				if(response.ok){
					localStorage.setItem('token', data.token);
					window.location.href = '/welcome';
				} else {
					document.getElementById('msgArea').innerHTML = `<div class="alert alert-info">Error : ${data.error}</div>`;
				}
			} catch(error){
				document.getElementById('msgArea').innerHTML = '<div class="alert alert-danger">Internal Server Error</div>';
			}
		});

		</script>
	

welcome.html
	
		<!doctype html>
		<html lang="en">
			<head>
				<!-- Required meta tags -->
				<meta charset="utf-8">
				<meta name="viewport" content="width=device-width, initial-scale=1">

				<!-- Bootstrap CSS -->
				<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

				<title>Node.js Login Register using JWT Token</title>
			</head>
			<body>
				
				<div class="container">
					<h1 class="text-center mb-5 mt-5">Node.js Login Register using JWT Token</h1>
					<div class="row">
						<div class="col col-4"> </div>
						<div class="col col-4">
							<span id="msgArea"></span>
							<div class="card">
								<div class="card-header">Welcome Page</div>
								<div class="card-body">
									<h1 class="text-center">Welcome User</h1>
									<p class="text-center">
										<button type="button" class="btn btn-warning" onclick="getJWTData()">Get User ID</button>
										<button type="button" onclick="logout()" class="btn btn-primary">Logout</button>
									</p>
								</div>
							</div>
						</div>
					</div>
				</div>

				<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
			</body>
		</html>

		<script>

		const token = localStorage.getItem('token');
		if(!token){
			window.location.href = '/login';
		}

		function logout(){
			localStorage.removeItem('token');
			window.location.href = '/login';
		}

		function getJWTData(){
			fetch('/getJWTData', {
				headers : {
					'Authorization' : token
				}
			})
			.then(response => {
				return response.json();
			})
			.then(data => {
				alert(`Login User ID is - ${data.userId}`);
			})
			.catch(error => {
				alert(error);
			});
		}

		</script>
	



Tuesday, 2 January 2024

Create a Secure Login with JWT Tokens in PHP: A Comprehensive Tutorial

In the world of web development, security is paramount, especially when it comes to user authentication. One effective way to enhance the security of your PHP applications is by implementing JWT (JSON Web Token) based login systems. In this comprehensive tutorial, we will guide you through the process of creating a secure login mechanism using JWT Tokens in PHP.

Create a Secure Login with JWT Tokens in PHP: A Comprehensive Tutorial

Why Choose JWT Tokens?


JWT Tokens offer a robust and efficient method for handling user authentication. They are compact, self-contained, and can be easily transmitted between parties. By leveraging JWT Tokens, you can ensure a secure and scalable login system for your PHP applications.

Prerequisites


Before we dive into the tutorial, make sure you have the following prerequisites in place:

  • Basic understanding of PHP programming.
  • A web server with PHP support.
  • A text editor for code editing.

Step 1: Setting Up Your PHP Environment


Begin by setting up your PHP environment. Ensure that you have PHP installed on your server, and create a new directory for your project. This will be the foundation for our secure login system.


// Sample PHP code for directory structure
/project-root
|-- index.php
|-- welcome.php
|-- logout.php
    |-- Before we dive into the tutorial, make sure you have the following prerequisites in place:





Step 2: Installing Dependencies


We will need a library to handle JWT operations. For this tutorial, we will use the popular `firebase/php-jwt` library. Install it using Composer:


composer require firebase/php-jwt


This library will simplify the creation, validation, and decoding of JWT Tokens in your PHP application.

Step 3: Creating the User Database


For our tutorial, let's assume you have a MySQL database named testing with a table named user. This table should contain fields like user_id, user_email, user_password, user_name and any other user-related information you need.


CREATE TABLE `user` (
  `user_id` int NOT NULL AUTO_INCREMENT,
  `user_email` varchar(70) DEFAULT NULL,
  `user_password` varchar(45) DEFAULT NULL,
  `user_name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO `user` VALUES (1,'johnsmith@gmail.com','password','John Smith');


Step 4: Building the Login System


Now, let's create the login system (login.php) that verifies user credentials and generates a JWT Token upon successful authentication.

index.php

<?php

//index.php

require 'vendor/autoload.php';

use Firebase\JWT\JWT;

$error = '';

if(isset($_POST["login"]))
{
	$connect = new PDO("mysql:host=localhost;dbname=testing", "root", "password");

	if(empty($_POST["email"])){
		$error = 'Please Enter Email Details';
	} else if(empty($_POST["password"])){
		$error = 'Please Enter Password Details';
	} else {
		$query = "SELECT * FROM user WHERE user_email = ?";
		$statement = $connect->prepare($query);
		$statement->execute([$_POST["email"]]);
		$data = $statement->fetch(PDO::FETCH_ASSOC);
		if($data){
			if($data['user_password'] ===  $_POST['password']){
				$key = '1a3LM3W966D6QTJ5BJb9opunkUcw_d09NCOIJb9QZTsrneqOICoMoeYUDcd_NfaQyR787PAH98Vhue5g938jdkiyIZyJICytKlbjNBtebaHljIR6-zf3A2h3uy6pCtUFl1UhXWnV6madujY4_3SyUViRwBUOP-UudUL4wnJnKYUGDKsiZePPzBGrF4_gxJMRwF9lIWyUCHSh-PRGfvT7s1mu4-5ByYlFvGDQraP4ZiG5bC1TAKO_CnPyd1hrpdzBzNW4SfjqGKmz7IvLAHmRD-2AMQHpTU-hN2vwoA-iQxwQhfnqjM0nnwtZ0urE6HjKl6GWQW-KLnhtfw5n_84IRQ';
				$token = JWT::encode(
					array(
						'iat'		=>	time(),
						'nbf'		=>	time(),
						'exp'		=>	time() + 3600,
						'data'	=> array(
							'user_id'	=>	$data['user_id'],
							'user_name'	=>	$data['user_name']
						)
					),
					$key,
					'HS256'
				);
				setcookie("token", $token, time() + 3600, "/", "", true, true);
				header('location:welcome.php');

			} else {
				$error = 'Wrong Password';
			}
		} else {
			$error = 'Wrong Email Address';
		}
	}
}

?>


<!doctype html>
<html lang="en">
  	<head>
    	<!-- Required meta tags -->
    	<meta charset="utf-8">
    	<meta name="viewport" content="width=device-width, initial-scale=1">

    	<!-- Bootstrap CSS -->
    	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    	<title>How to Create Login using JWT Token in PHP</title>
  	</head>
  	<body>
    	<div class="container">
    		<h1 class="text-center mt-5 mb-5">How to Create Login using JWT Token in PHP</h1>
    		<div class="row">
    			<div class="col-md-4">&nbsp;</div>
    			<div class="col-md-4">
    				<?php

    				if($error !== '')
    				{
    					echo '<div class="alert alert-danger">'.$error.'</div>';
    				}

    				?>
		    		<div class="card">
		    			<div class="card-header">Login</div>
		    			<div class="card-body">
		    				<form method="post">
		    					<div class="mb-3">
			    					<label>Email</label>
			    					<input type="email" name="email" class="form-control" />
			    				</div>
			    				<div class="mb-3">
			    					<label>Password</label>
			    					<input type="password" name="password" class="form-control" />
			    				</div>
			    				<div class="text-center">
			    					<input type="submit" name="login" class="btn btn-primary" value="Login" />
			    				</div>
		    				</form>
		    			</div>
		    		</div>
		    	</div>
	    	</div>
    	</div>
  	</body>
</html>


The above code is a PHP script that handles user authentication using JWT (JSON Web Token) in a web application. This above code demonstrates a basic user authentication flow using JWT tokens in PHP, integrating database queries, JWT token generation, and error handling for a secure login system. Make sure to adapt and enhance it according to your specific project requirements and security considerations.

The HTML section contains a simple form for user login. It uses Bootstrap for styling.

welcome.php

<?php

//welcome.php

require 'vendor/autoload.php';

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$key = '1a3LM3W966D6QTJ5BJb9opunkUcw_d09NCOIJb9QZTsrneqOICoMoeYUDcd_NfaQyR787PAH98Vhue5g938jdkiyIZyJICytKlbjNBtebaHljIR6-zf3A2h3uy6pCtUFl1UhXWnV6madujY4_3SyUViRwBUOP-UudUL4wnJnKYUGDKsiZePPzBGrF4_gxJMRwF9lIWyUCHSh-PRGfvT7s1mu4-5ByYlFvGDQraP4ZiG5bC1TAKO_CnPyd1hrpdzBzNW4SfjqGKmz7IvLAHmRD-2AMQHpTU-hN2vwoA-iQxwQhfnqjM0nnwtZ0urE6HjKl6GWQW-KLnhtfw5n_84IRQ';

if(isset($_COOKIE['token'])){
	$decoded = JWT::decode($_COOKIE['token'], new Key($key, 'HS256'));
} else {
	header('location:index.php');
}

?>

<!doctype html>
<html lang="en">
  	<head>
    	<!-- Required meta tags -->
    	<meta charset="utf-8">
    	<meta name="viewport" content="width=device-width, initial-scale=1">

    	<!-- Bootstrap CSS -->
    	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    	<title>How to Create Login in PHP using JWT Token</title>
  	</head>
  	<body>
    	<div class="container">
    		<h1 class="text-center mt-5 mb-5">How to Create Login in PHP using JWT Token</h1>
    		<div class="row">
    			<div class="col-md-4">&nbsp;</div>
    			<div class="col-md-4 text-center">
    				<h1>Welcome <b><?php echo $decoded->data->user_name; ?></b></h1>
    				<a href="logout.php">Logout</a>
    				
		    	</div>
	    	</div>
    	</div>
  	</body>
</html>


This PHP script (welcome.php) is responsible for displaying a welcome page for authenticated users.

This script checks for a valid JWT token in the user's cookie. If a token is present, it decodes the token to retrieve user information and displays a welcome message. If no token is found, the user is redirected to the login page. The welcome page includes a logout link, which presumably leads to a logout script (logout.php).

logout.php

<?php

//logout.php

setcookie("token", "", time() - 3600,  "/", "", true, true);

header('location:index.php');

?>





The provided PHP script (logout.php) is responsible for logging out a user from the application.

This script is a simple logout mechanism for a web application. It clears the authentication token stored in the user's browser by deleting the corresponding cookie and then redirects the user to the login page to ensure a logged-out state. This is a common practice to terminate a user's session and enhance security.

Conclusion


Congratulations! You've successfully created a secure login system using JWT Tokens in PHP. This comprehensive tutorial covered setting up your PHP environment, installing dependencies, creating a user database, implementing user registration, building the login system, and securing your application.

By following these steps, you've enhanced the security of your PHP application, providing a robust authentication mechanism for your users. Implementing JWT-based login systems is a crucial step towards creating secure, scalable, and reliable web applications.

Feel free to adapt and expand upon this tutorial to meet the specific requirements of your project. Happy coding!

Remember to regularly update your dependencies, follow best practices, and stay informed about the latest security standards to ensure the ongoing security of your PHP applications.