-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathauth.js
More file actions
56 lines (52 loc) · 2.25 KB
/
auth.js
File metadata and controls
56 lines (52 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import jwt from "jsonwebtoken";
import { APS_CLIENT_ID, APS_CLIENT_SECRET, SSA_ID, SSA_KEY_ID, SSA_KEY_BASE64 } from "./config.js";
export async function getServiceAccountAccessToken(scopes) {
const privateKey = decodePrivateKey(SSA_KEY_BASE64);
const assertion = createAssertion(APS_CLIENT_ID, SSA_ID, SSA_KEY_ID, privateKey, scopes);
return getAccessToken(APS_CLIENT_ID, APS_CLIENT_SECRET, "urn:ietf:params:oauth:grant-type:jwt-bearer", scopes, assertion);
}
function decodePrivateKey(base64Value) {
if (typeof base64Value !== "string" || base64Value.trim() === "") {
throw new Error("SSA_KEY_BASE64 is missing or empty.");
}
const normalized = base64Value.replace(/\s+/g, "");
const decoded = Buffer.from(normalized, "base64").toString("utf-8");
if (!decoded.includes("BEGIN PRIVATE KEY") && !decoded.includes("BEGIN RSA PRIVATE KEY")) {
throw new Error("SSA_KEY_BASE64 does not decode to a valid PEM private key.");
}
return decoded;
}
function createAssertion(clientId, serviceAccountId, serviceAccountKeyId, serviceAccountPrivateKey, scopes) {
const payload = {
iss: clientId,
sub: serviceAccountId,
aud: "https://developer.api.autodesk.com/authentication/v2/token",
exp: Math.floor(Date.now() / 1000) + 300, // 5 minutes
scope: scopes
};
return jwt.sign(payload, serviceAccountPrivateKey, {
algorithm: "RS256",
header: {
alg: "RS256",
kid: serviceAccountKeyId
},
noTimestamp: true
});
}
async function getAccessToken(clientId, clientSecret, grantType, scopes, assertion) {
const headers = {
"Accept": "application/json",
"Authorization": `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
"Content-Type": "application/x-www-form-urlencoded"
};
const body = new URLSearchParams({
"grant_type": grantType,
"scope": scopes.join(" "),
"assertion": assertion
});
const response = await fetch("https://developer.api.autodesk.com/authentication/v2/token", { method: "POST", headers, body });
if (!response.ok) {
throw new Error(`Could not generate access token: ${await response.text()}`);
}
return response.json();
}