-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
adobe-ims-servicetoken.js
103 lines (91 loc) · 2.47 KB
/
adobe-ims-servicetoken.js
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* adobe-ims-servicetoken
*
* @copyright 2023 Jason Mulligan <jason.mulligan@avoidwork.com>
* @license BSD-3-Clause
* @version 3.0.8
*/
import {createHash}from'node:crypto';const AMPERSAND = "&";
const BASE64 = "base64";
const CLIENT_ID = "client_id";
const CLIENT_SECRET = "client_secret";
const CODE = "code";
const CONTENT_TYPE = "content-type";
const DEFAULT_GRANT_TYPE = "authorization_code";
const DEFAULT_URL = "https://ims-na1.adobelogin.com/ims/token";
const EMPTY = "";
const FORM_URLENCODED = "application/x-www-form-urlencoded";
const GRANT_TYPE = "grant_type";
const JWT_TOKEN = "jwt_token";
const POST = "POST";
const SHA1 = "sha1";
const STRING = "string";const tokens = new Map();
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); // eslint-disable-line no-shadow
async function token ({
url = DEFAULT_URL,
grant_type = DEFAULT_GRANT_TYPE,
client_id = EMPTY,
client_secret = EMPTY,
code = EMPTY,
jwt_token = EMPTY
} = {}) {
const key = createHash(SHA1).update(`${url}|${client_id}|${grant_type}`).digest(BASE64);
let result;
if (tokens.has(key) === false) {
const body = [
`${CLIENT_ID}=${client_id}`,
`${CLIENT_SECRET}=${client_secret}`
];
let res;
if (grant_type.length > 0) {
body.push(`${GRANT_TYPE}=${grant_type}`);
}
if (code.length > 0) {
body.push(`${CODE}=${code}`);
}
if (jwt_token.length > 0) {
body.push(`${JWT_TOKEN}=${jwt_token}`);
}
try {
res = await fetch(url, {
method: POST,
headers: {
[CONTENT_TYPE]: FORM_URLENCODED
},
body: body.join(AMPERSAND)
});
} catch (err) {
res = {
ok: false,
statusText: err.message || err,
json: async () => {
return {
error: res.statusText,
error_description: err.message
};
},
text: async () => err.message || err
};
}
if (res.ok) {
const data = await res.clone().json();
tokens.set(key, data.access_token);
result = structuredClone(data.access_token);
if (data.expires_in !== void 0) {
setTimeout(() => tokens.delete(key), data.expires_in); // 24hr validity at time of dev
}
} else {
let data;
try {
data = await res.clone().json();
} catch (err) {
data = await res.clone().text();
}
const errorMsg = typeof data === STRING ? res.statusText : `${data?.error}: ${data?.error_description}`;
throw new Error(`[${res.status}] ${errorMsg}`);
}
} else {
result = structuredClone(tokens.get(key));
}
return result;
}export{token};