const { test } = require("node:test"); const assert = require("node:assert"); const crypto = require("node:crypto"); const { buildAssertion, fetchAccessToken } = require("../src/lib/lineworksAuth"); function base64urlDecode(str) { return Buffer.from(str.replace(/-/g, "+").replace(/_/g, "/"), "base64"); } test("buildAssertion produces a valid RS256 JWT signed with the given private key", () => { const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048 }); const now = new Date("2026-08-08T00:00:00Z").getTime(); const jwt = buildAssertion({ clientId: "test-client-id", serviceAccount: "svc@example.com", privateKey: privateKey.export({ type: "pkcs1", format: "pem" }), now, }); const [headerB64, payloadB64, sigB64] = jwt.split("."); const header = JSON.parse(base64urlDecode(headerB64).toString("utf8")); const payload = JSON.parse(base64urlDecode(payloadB64).toString("utf8")); assert.deepStrictEqual(header, { alg: "RS256", typ: "JWT" }); assert.strictEqual(payload.iss, "test-client-id"); assert.strictEqual(payload.sub, "svc@example.com"); assert.strictEqual(payload.exp - payload.iat, 3600); const verifier = crypto.createVerify("RSA-SHA256"); verifier.update(`${headerB64}.${payloadB64}`); const isValid = verifier.verify(publicKey, base64urlDecode(sigB64)); assert.strictEqual(isValid, true); }); test("fetchAccessToken posts a jwt-bearer grant and returns the access_token", async () => { const { privateKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048 }); let capturedBody; const fetchImpl = async (url, opts) => { capturedBody = opts.body; return { ok: true, json: async () => ({ access_token: "fake-token", expires_in: 3600 }), }; }; const token = await fetchAccessToken({ clientId: "cid", clientSecret: "secret", serviceAccount: "svc@example.com", privateKey: privateKey.export({ type: "pkcs1", format: "pem" }), scope: "directory.read", fetchImpl, }); assert.strictEqual(token, "fake-token"); assert.ok(capturedBody.includes("grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer")); assert.ok(capturedBody.includes("client_id=cid")); });