Protect Your REST APIs using JWT.
In this tutorial, We will learn to protect REST APIs using JSON Web Token with an example.
What is JSON Web Token aka JWT?
JSON Web Token (JWT) is way of authenticating user on internet. As name suggest it is JSON based taken. The token is signed using private secret key or public key. For example, a server could generate token which user login and provide to the client. This token could signed using user_id or email with secret key and expiration timestamp. This token payload used when client need to authenticate on server.
JWT is mostly useful for REST APIs, mobile apps, Single Page Web Apps, etc.
Software requirements
- Node.js — Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine.
- Express — Fast, unopinionated, minimalist web framework for Node.js
- jsonwebtoken —An implementation of JSON Web Tokens.
- bcrypt — A library to help you hash passwords.
- body-parser — Node.js body parsing middleware.
- Postman — A collaboration platform for API development.
Project setup
We will be using the Express framework for this project. Of course, you’ll need to have Node installed.
Create a directory for our project, navigate into the directory, and issue npm init
to create a .json file that manages all the dependencies for our application
Install the required packages using npm command:
npm install --save express body-parser bcrypt jsonwebtoken
Import required packages and create a server
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));const PORT = 3000;app.listen(3000, () => console.log('Server running on ' + PORT));
We implement an authentication process.
So we create three routes,
- Users can sign up using this route.
http://localhost:3000/signup
2. Users can sign in using this route.
http://localhost:3000/signin
After signing we return JWT token to the user. Using this token user can access protected routes.
3. Users can access posts using this route.
http://localhost:3000/posts
To access posts, a user requires a JWT token.
Now create users
and posts
array to store users and posts.
var users = [];
var posts = [{
'title': 'This is title of post',
'description': 'This is description of post'
}];
Create the above mentioned routes to accept data from the client.
Implement Sign up a route:
app.post('/signup', (req, res, next) => {
const { username, password } = req.body;
//Check for user already exists or not
users.forEach(user => {
if (user.username == username) {
return res.status(409).json({
message: 'User already exists'
});
}
});
//Eles push new user into database or array
const user = { username, password };
//Hash password and create token
const hashedPassword = bcrypt.hash(password, 10);
users.push(user, hashedPassword);return res.status(201).json({
message: 'User has been created'
});});
In the above route, we are accepting username
and password
from req.body
.
Next, we check user already exists or not. If doesn't exist, add to database or array.
Implement Sign in a route:
app.post('/signin', (req, res, next) => {
const { username, password } = req.body;
//Signin
users.forEach(user => {
if (user.username == username && bcrypt.compare(password, user.password)) {
const token = jwt.sign({
username: user.username
}, 'secretKey', { expiresIn: '1h' });
return res.status(200).json({
message: 'Signin successful',
token: token
});
}
return res.status(401).json({
message: 'Auth failed'
});
});
return res.status(401).json({
message: 'Auth failed'
});
});
Let me explain here, we are creating JWT Payload Token here.
const token = jwt.sign({
username: user.username
}, 'secretKey', { expiresIn: '1h' });
return res.status(200).json({
message: 'Signin successful',
token: token
});
We wrapping username
, secret key
and token expire timestamp in hours
.
jwt.sign()
method will return hashed token
.
We return this token to the user.
Now implement a protected route.
Post route:
app.get('/posts', (req, res, next) => {
const token = req.headers.authorization.split(' ')[1];
const decode = jwt.verify(token, 'secretKey');
req.decode = decode;
next();
}, (req, res, next) => {
return res.status(200).json(posts);
});
Here, implementing middleware to receive token
from req.headers
.
Now verify received token
with secret key
.
If it validates all token, all posts will be sent to the user.