const express = require("express"); const crypto = require("crypto"); const querystring = require("querystring"); const jwt = require("jsonwebtoken"); const jwksClient = require("jwks-rsa"); const app = express(); const CLIENT_ID = "ec014b23-edde-4a09-9a41-36bff5630829"; // appID const CLIENT_SECRET = "Y.Q8Q~HuoEbCsICK18eG4oAtqjMe5eGyWSilLaZI"; // appid secret const TENANT = "publicanub.onmicrosoft.com"; const TENANT_ID = "23c95e59-28bd-472a-bbd4-4e310dd8f031"; // organisation id const REDIRECT_URI = "http://localhost:3000/callback"; const AUTH_URL = `https://login.microsoftonline.com/${TENANT}/oauth2/v2.0`; const SCOPES = "openid profile email"; // Fetch Microsoft's public key by kid to verify JWT signatures const keys = jwksClient({ jwksUri: "https://login.microsoftonline.com/common/discovery/v2.0/keys" }); function getKey(header, cb) { keys.getSigningKey(header.kid, (err, key) => cb(err, key?.getPublicKey())); } function verifyJwt(token) { return new Promise((resolve, reject) => { jwt.verify(token, getKey, { audience: CLIENT_ID, // Multi-tenant: accept tokens from any Azure AD tenant issuer: (iss) => iss.startsWith("https://login.microsoftonline.com/") && iss.endsWith("/v2.0"), algorithms: ["RS256"], }, (err, decoded) => err ? reject(err) : resolve(decoded)); }); } // POST to Microsoft's token endpoint function fetchTokens(code) { return new Promise((resolve, reject) => { const body = querystring.stringify({ client_id: CLIENT_ID, client_secret: CLIENT_SECRET, grant_type: "authorization_code", code, redirect_uri: REDIRECT_URI, scope: SCOPES, }); const req = require("https").request({ hostname: "login.microsoftonline.com", path: `/${TENANT}/oauth2/v2.0/token`, method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "Content-Length": Buffer.byteLength(body) }, }, (res) => { let data = ""; res.on("data", (c) => data += c); res.on("end", () => resolve(JSON.parse(data))); }); req.on("error", reject); req.write(body); req.end(); }); } app.get("/", (_, res) => res.send('
Error: ${error}: ${error_description}`);
try {
const tokens = await fetchTokens(code);
if (tokens.error) return res.send(`Token error: ${JSON.stringify(tokens, null, 2)}Home`);
// Verify JWT signature against Microsoft's public key + check aud, iss, exp
const v = await verifyJwt(tokens.id_token);
// // Only allow specific tenants
// const ALLOWED_TENANTS = ["23c95e59-28bd-472a-bbd4-4e310dd8f031"];
// if (!ALLOWED_TENANTS.includes(v.tid)) {
// return res.status(403).send(`Tenant not allowed: ${v.tid}Home`);
// }
res.send(`
${JSON.stringify(req.query, null, 2)}
This code was exchanged + client_secret for the tokens below
Signature: VALID (RS256, Microsoft public key)
Audience: ${v.aud} | Issuer: ${v.iss} (tenant: ${v.tid})
Expires: ${new Date(v.exp * 1000).toISOString()}
oid: ${v.oid} | ${v.name} | ${v.preferred_username}
${JSON.stringify(v, null, 2)}
Start over
`);
} catch (err) {
res.status(401).send(`JWT verification failed: ${err.message}Try again`);
}
});
app.listen(3000, () => console.log("http://localhost:3000"));