How to implement API Authentication with JSON Web Tokens and Passport

Many web applications and APIs use a form of authentication to protect resources and restrict their access only to verified users. This guide will walk you through how to implement authentication for an API using Json Web Tokens (JWTs) and Passport.

Passport is a Node.js middle-ware that offers a variety of different request authentication strategies that are easy to implement. By default, it stores the user object in session.

JSON Web Tokens is an authentication standard that works by assigning and passing around an encrypted token in requests that helps to identify the logged in user, instead of storing the user in a session on the server and creating a cookie.

Let’s start.

Make folder using following command.

mkdir passportverify

Go to folder and add package.json file

cd passportverify
npm init -y

Install express , cors , dotenv (to store secret key to .env file) ,passport and passport JWT, jsonwebtoken.

npm install express cors dotenv
npm install passport passport-jwt jsonwebtoken

So your package.json will look like as following

{
"name": "passportverify",
"version": "1.0.0",
"description": "",
"main": "server.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"passport": "^0.5.0",
"passport-jwt": "^4.0.0"
}
}

create server.js file in root of folder.

import express from "express";
import cors from "cors";
import passport from "passport";
import routes from "./api/route.js";
import dotenv from "dotenv";
import { applyPassportStrategy } from "./store/passport.js";
const app = express();
dotenv.config();
app.use(cors());
app.use(passport.initialize());
applyPassportStrategy(passport);
app.use(express.json());
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS, PUT, PATCH, DELETE"
);
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use("/api/", routes);
const port = process.env.PORT;
app.listen(port, () => {
console.log("listening to port");
});
export default app;

Now create Strategy. so go to store folder and create passport.js file.

Add following code.

import { Strategy, ExtractJwt } from "passport-jwt";
export const applyPassportStrategy = (passport) => {
const options = {};
options.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
options.secretOrKey = process.env.SECRET;
passport.use(
new Strategy(options, (payload, done) => {
if (payload.email) {
return done(null, {
email: payload.email,
});
} else {
return done(null, false);
}
})
);
};

Now add routes in api folder. create route.js and add following routes.

import express from "express";
import SuppliersCtrl from "./suppliers.controller.js";
import passport from "passport";
const router = express.Router();
router.route("/login").post(SuppliersCtrl.apiPostLogin);
router.get(
"/test",
passport.authenticate("jwt", { session: false }),
SuppliersCtrl.apiTest
);
export default router;

add controller folder and create suppliers.controller.js.

import jwt from "jsonwebtoken";export default class SuppliersController {
static async apiPostLogin(req, res, next) {
try {
let payload = {
id: 1,
email: "test@tes.com",
iat: Math.floor(Date.now() / 1000),
};
const key = process.env.SECRET;
console.log(key);
let token = await SuppliersController.doRequest(payload, key);
res.json({
status: "success",
token: `Bearer ${token}`,
});
} catch (e) {
res.status(500).json({ error: e.message });
}
}
static async doRequest(payload, key) {
try {
return new Promise(function (resolve, reject) {
jwt.sign(
payload,
key,
{
expiresIn: "10d",
},
(err, token) => {
console.log(token);
if (token) {
resolve(token);
} else {
console.log(err);
reject(new Error("not OK"));
}
}
);
});
} catch (error) {}
}
static async apiTest(req, res, next) {
try {
res.json({
status: "success",
});
} catch (e) {
res.status(500).json({ error: e.message });
}
}
}

So to access this open postman and make post request

URL : http://localhost:4567/api/login

response will be like

{
"status": "success",
"token": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJ0ZXN0QHRlcy5jb20iLCJpYXQiOjE2Mzg4NjcyMTYsImV4cCI6MTYzOTczMTIxNn0.Nq3w0jkLygQdnoetyFhULTgDXEOBqLjnUtJU5NIM1mI"
}

Take token value from response and pass to header.

URL : http://localhost:4567/api/test

If there token is correct and not expired then it will return success otherwise it will return Unauthorized.

You can get code here. https://github.com/stemword/API-Authentication-with-JSON-Web-Tokens-and-Passport

You can also checkout YouTube channel : https://www.youtube.com/channel/UCOWT2JvRnSMVSboxvccZBFQ

--

--

--

Developer by profession . Youtube channel : https://www.youtube.com/channel/UCOWT2JvRnSMVSboxvccZBFQ

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Leetcode — Minimum Add to Make Parentheses Valid

Test Axios call in async function using JEST with TypeScript

Hoisting (JavaScript)

When to destructure props in React?

Microsoft App Center Build process Customization

Why state management ?

Software Engineer’s Job Hunting — Portfolio with React.js and Github Pages

The Iterator Giveth

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Code With Travel

Code With Travel

Developer by profession . Youtube channel : https://www.youtube.com/channel/UCOWT2JvRnSMVSboxvccZBFQ

More from Medium

How to Build an API using Strapi

JWT Auth and Request Transform with Express Gateway

Setting up SSH key for Bitbucket account on macOS

Develop clean MVC web applications with Nest.js