Last active
October 6, 2022 07:58
-
-
Save AvinashSKaranth/55297f02ef4ae1a3d696868b528e4d4f to your computer and use it in GitHub Desktop.
JWT Security for Offline Token Generation and Validation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Client side Offline Token Generation | |
require("dotenv").config(); | |
const http = require("http"); | |
const jwt = require("jsonwebtoken"); | |
const token = jwt.sign({ method: "send" }, process.env.CLIENT_SECRET, { | |
algorithm: "HS256", | |
header: { typ: "JWT", kid: process.env.CLIENT_ID }, | |
}); | |
const postData = JSON.stringify({ | |
somedata: "123", | |
}); | |
const options = { | |
hostname: "localhost", | |
port: process.env.PORT, | |
path: "/path/to/api", | |
method: "POST", | |
headers: { | |
"Content-Type": "application/json", | |
"Content-Length": postData.length, | |
Authorization: "Bearer " + token, | |
}, | |
}; | |
const req = http.request(options, (res) => { | |
console.log("statusCode:", res.statusCode); | |
console.log("headers:", res.headers); | |
res.on("data", (d) => { | |
process.stdout.write(d); | |
}); | |
}); | |
req.on("error", (e) => { | |
console.error(e); | |
}); | |
req.write(postData); | |
req.end(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Load all CLIENT_ID and CLIENT_SECRET to a inMemory hash | |
// Move require("./client.json"); to a API call to support dynamically created | |
// You can repl | |
let credentials = {}; | |
if (fs.existsSync("./client.json")) { | |
credentials = require("./client.json"); | |
} else { | |
const CLIENT_ID = process.env.CLIENT_ID || ""; | |
const CLIENT_SECRET = process.env.CLIENT_SECRET || ""; | |
if (CLIENT_ID !== "" && CLIENT_SECRET !== "") { | |
credentials[CLIENT_ID] = CLIENT_SECRET; | |
} | |
} | |
// Middleware for Validation of offline Token | |
// You can add object to request object in the middleware (Example: req.client = getClientDetails("kid")) | |
app.use(authorizeJWT); | |
const authorizeJWT = function (req, res, next) { | |
if (!req.headers.hasOwnProperty("authorization")) { | |
res.status(401).send({ message: "Authorization Bearer Token is required" }); | |
} | |
if (!req.headers.authorization.startsWith("Bearer ")) { | |
res.status(401).send({ message: "Authorization Bearer Token is required" }); | |
} | |
let token = req.headers.authorization | |
.toString() | |
.replace("Bearer ", "") | |
.trim(); | |
let kid = ""; | |
try { | |
kid = JSON.parse(Buffer.from(token.toString().split(".")[0], "base64"))[ | |
"kid" | |
]; | |
} catch (err) { | |
res | |
.status(401) | |
.send({ message: "kid must be passed in the JsonWebToken header" }); | |
} | |
jwt.verify(token, credentials[kid], function (err, decoded) { | |
if (err || decoded === undefined) { | |
res.status(401).send({ message: "Unauthorized" }); | |
} else { | |
try { | |
if (Math.abs(decoded.iat - new Date().getTime() / 1000) < 300) { | |
next(); | |
} else { | |
res.status(401).send({ message: "Token Expired" }); | |
} | |
} catch (_err) { | |
res.status(401).send({ message: "Invalid Token" }); | |
} | |
} | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment