-
Notifications
You must be signed in to change notification settings - Fork 19
/
browser.js
116 lines (102 loc) · 3.34 KB
/
browser.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
104
105
106
107
108
109
110
111
112
113
114
115
116
// you should also add this line:
// <script src="https://cdn.jsdelivr.net/npm/uuid/dist/umd/uuidv1.min.js"></script>
// which imports `uuidv1()` function
/**
* Usage:
* ```js
* await NetlessToken.sdkToken("ak", "sk", 60 * 1000,
* { role: NetlessToken.TokenRole.Admin });
* await NetlessToken.roomToken("ak", "sk", 60 * 1000,
* { role: NetlessToken.TokenRole.Writer, uuid: <room uuid> });
* await NetlessToken.taskToken("ak", "sk", 60 * 1000,
* { role: NetlessToken.TokenRole.Reader, uuid: <task uuid> });
* ```
*/
var NetlessToken = (function (exports, uuidv1) {
const TokenRole = {
Admin: "0",
Writer: "1",
Reader: "2",
};
exports.TokenRole = TokenRole;
const TokenPrefix = {
SDK: "NETLESSSDK_",
ROOM: "NETLESSROOM_",
TASK: "NETLESSTASK_",
};
exports.TokenPrefix = TokenPrefix;
function formatJSON(obj) {
const keys = Object.keys(obj).sort();
const target = {};
for (const key of keys) {
target[key] = String(obj[key]);
}
return target;
}
function stringify(obj) {
return Object.keys(obj)
.map((key) => {
const value = obj[key];
if (value === undefined) return "";
if (value === null) return "null";
return `${encodeURIComponent(key)}=${encodeURIComponent(
value
)}`;
})
.join("&");
}
const encoder = new TextEncoder("utf-8");
async function createHmac(hash, secretKey) {
if (hash === "sha256") hash = "SHA-256";
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(secretKey),
{
name: "HMAC",
hash: hash,
},
true,
["sign", "verify"]
);
return {
data: "",
update(str) {
this.data += str;
return this;
},
async digest() {
const data = encoder.encode(this.data);
const sig = await crypto.subtle.sign("HMAC", key, data);
const b = Array.from(new Uint8Array(sig));
return b.map((x) => x.toString(16).padStart(2, "0")).join("");
},
};
}
function createToken(prefix) {
return async (accessKey, secretAccessKey, lifespan, content) => {
const object = {
...content,
ak: accessKey,
nonce: uuidv1(),
};
if (lifespan > 0) {
object.expireAt = `${Date.now() + lifespan}`;
}
const information = JSON.stringify(formatJSON(object));
const hmac = await createHmac("sha256", secretAccessKey);
object.sig = await hmac.update(information).digest("hex");
const query = stringify(formatJSON(object));
return (
prefix +
btoa(query)
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "")
);
};
}
exports.sdkToken = createToken(TokenPrefix.SDK);
exports.roomToken = createToken(TokenPrefix.ROOM);
exports.taskToken = createToken(TokenPrefix.TASK);
return exports;
})({}, uuidv1);