Implementing JWT Authentication in Node.js Without Libraries
Introduction
Understanding JWT internals boosts security and reduces dependencies. This guide explains how to create and verify JSON Web Tokens in pure Node.js.
Prerequisites
- Node.js >=14
Step 1: Utility Functions
Create jwt.js
:
const crypto = require("crypto");
function base64UrlEncode(str) {
return Buffer.from(str)
.toString("base64")
.replace(/=/g, "")
.replace(/\+/g, "-")
.replace(/\//g, "_");
}
function sign(header, payload, secret) {
const encodedHeader = base64UrlEncode(JSON.stringify(header));
const encodedPayload = base64UrlEncode(JSON.stringify(payload));
const signature = crypto
.createHmac("sha256", secret)
.update(`${encodedHeader}.${encodedPayload}`)
.digest("base64")
.replace(/=/g, "")
.replace(/\+/g, "-")
.replace(/\//g, "_");
return `${encodedHeader}.${encodedPayload}.${signature}`;
}
function verify(token, secret) {
const [headerB64, payloadB64, signature] = token.split(".");
const expectedSig = crypto
.createHmac("sha256", secret)
.update(`${headerB64}.${payloadB64}`)
.digest("base64")
.replace(/=/g, "")
.replace(/\+/g, "-")
.replace(/\//g, "_");
return signature === expectedSig;
}
module.exports = { sign, verify };
Step 2: Use in Server
Create server.js
:
const http = require("http");
const { sign, verify } = require("./jwt");
const SECRET = "mysecret";
const server = http.createServer((req, res) => {
if (req.url === "/login") {
const token = sign({ alg: "HS256", typ: "JWT" }, { user: "alice" }, SECRET);
return res.end(token);
}
if (req.url === "/protected") {
const token = req.headers["authorization"];
if (!token || !verify(token, SECRET)) {
res.statusCode = 401;
return res.end("Unauthorized");
}
return res.end("Protected data");
}
res.end("OK");
});
server.listen(3000);