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