-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
get-token.js
58 lines (48 loc) · 1.7 KB
/
get-token.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
// we don't @ts-check here because it chokes crypto which is a global API in modern JS runtime environments
import {
getEncodedMessage,
getDERfromPEM,
string2ArrayBuffer,
base64encode,
} from "./utils.js";
/**
* @param {import('../internals').GetTokenOptions} options
* @returns {Promise<string>}
*/
export async function getToken({ privateKey, payload }) {
// WebCrypto only supports PKCS#8, unfortunately
if (privateKey.includes("-----BEGIN RSA PRIVATE KEY-----")) {
throw new Error(
"[universal-github-app-jwt] Private Key is in PKCS#1 format, but only PKCS#8 is supported by WebCrypto. See https://github.com/gr2m/universal-github-app-jwt#readme"
);
}
// WebCrypto does not support OpenSSH, unfortunately
if (privateKey.includes("-----BEGIN OPENSSH PRIVATE KEY-----")) {
throw new Error(
"[universal-github-app-jwt] Private Key is in OpenSSH format, but only PKCS#8 is supported by WebCrypto. See https://github.com/gr2m/universal-github-app-jwt#readme"
);
}
const algorithm = {
name: "RSASSA-PKCS1-v1_5",
hash: { name: "SHA-256" },
};
/** @type {import('../internals').Header} */
const header = { alg: "RS256", typ: "JWT" };
const privateKeyDER = getDERfromPEM(privateKey);
const importedKey = await crypto.subtle.importKey(
"pkcs8",
privateKeyDER,
algorithm,
false,
["sign"]
);
const encodedMessage = getEncodedMessage(header, payload);
const encodedMessageArrBuf = string2ArrayBuffer(encodedMessage);
const signatureArrBuf = await crypto.subtle.sign(
algorithm.name,
importedKey,
encodedMessageArrBuf
);
const encodedSignature = base64encode(signatureArrBuf);
return `${encodedMessage}.${encodedSignature}`;
}