@authup/server-kit 1.0.0-beta.33 → 1.0.0-beta.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +379 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +674 -924
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
package/dist/index.mjs
CHANGED
|
@@ -1,988 +1,738 @@
|
|
|
1
|
-
import { compare as compare$1, hash as hash$1 } from
|
|
2
|
-
import { arrayBufferToBase64, base64ToArrayBuffer, isObject
|
|
3
|
-
import { JWTAlgorithm, JWTError
|
|
4
|
-
import { subtle } from
|
|
5
|
-
import { Algorithm, sign, verify } from
|
|
6
|
-
import { isObject } from
|
|
7
|
-
import { TTLCache } from
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
import { Emitter } from '@socket.io/redis-emitter';
|
|
18
|
-
|
|
1
|
+
import { compare as compare$1, hash as hash$1 } from "@node-rs/bcrypt";
|
|
2
|
+
import { arrayBufferToBase64, base64ToArrayBuffer, isObject } from "@authup/kit";
|
|
3
|
+
import { JWKType, JWTAlgorithm, JWTError } from "@authup/specs";
|
|
4
|
+
import { subtle } from "uncrypto";
|
|
5
|
+
import { Algorithm, sign, verify } from "@node-rs/jsonwebtoken";
|
|
6
|
+
import { isObject as isObject$1 } from "smob";
|
|
7
|
+
import { TTLCache } from "@isaacs/ttlcache";
|
|
8
|
+
import { Client as RedisClient, JsonAdapter, JsonAdapter as RedisJsonAdapter, Watcher as RedisWatcher, buildKeyPath as buildRedisKeyPath, createClient, escapeKey as escapeRedisKey, parseKeyPath as parseRedisKeyPath } from "redis-extension";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import process from "node:process";
|
|
11
|
+
import { Logger, createLogger as createLogger$1, format, transports } from "winston";
|
|
12
|
+
import { singa } from "singa";
|
|
13
|
+
import { VaultClient, createClient as createVaultClient } from "@hapic/vault";
|
|
14
|
+
import { buildEventFullName } from "@authup/core-realtime-kit";
|
|
15
|
+
import { Emitter } from "@socket.io/redis-emitter";
|
|
16
|
+
//#region src/crypto/hash/compare.ts
|
|
19
17
|
async function compare(value, hashedValue) {
|
|
20
|
-
|
|
18
|
+
return compare$1(value, hashedValue);
|
|
21
19
|
}
|
|
22
|
-
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/crypto/hash/hash.ts
|
|
23
22
|
async function hash(str, rounds = 10) {
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
CryptoAsymmetricAlgorithm["RSA_OAEP"] = "RSA-OAEP";
|
|
36
|
-
CryptoAsymmetricAlgorithm["ECDSA"] = "ECDSA";
|
|
37
|
-
CryptoAsymmetricAlgorithm["ECDH"] = "ECDH";
|
|
38
|
-
return CryptoAsymmetricAlgorithm;
|
|
23
|
+
return hash$1(str, rounds);
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/crypto/key/asymmetric/constants.ts
|
|
27
|
+
let CryptoAsymmetricAlgorithm = /* @__PURE__ */ function(CryptoAsymmetricAlgorithm) {
|
|
28
|
+
CryptoAsymmetricAlgorithm["RSA_PSS"] = "RSA-PSS";
|
|
29
|
+
CryptoAsymmetricAlgorithm["RSASSA_PKCS1_V1_5"] = "RSASSA-PKCS1-v1_5";
|
|
30
|
+
CryptoAsymmetricAlgorithm["RSA_OAEP"] = "RSA-OAEP";
|
|
31
|
+
CryptoAsymmetricAlgorithm["ECDSA"] = "ECDSA";
|
|
32
|
+
CryptoAsymmetricAlgorithm["ECDH"] = "ECDH";
|
|
33
|
+
return CryptoAsymmetricAlgorithm;
|
|
39
34
|
}({});
|
|
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
|
-
* Copyright (c) 2024-2024.
|
|
72
|
-
* Author Peter Placzek (tada5hi)
|
|
73
|
-
* For the full copyright and license information,
|
|
74
|
-
* view the LICENSE file that was distributed with this source code.
|
|
75
|
-
*/ function enc(type, input) {
|
|
76
|
-
return `-----BEGIN ${type}-----\n${input}\n-----END ${type}-----`;
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/crypto/key/base.ts
|
|
37
|
+
var BaseKey = class {
|
|
38
|
+
key;
|
|
39
|
+
constructor(cryptoKey) {
|
|
40
|
+
this.key = cryptoKey;
|
|
41
|
+
}
|
|
42
|
+
async toArrayBuffer() {
|
|
43
|
+
if (this.key.type === "private") return subtle.exportKey("pkcs8", this.key);
|
|
44
|
+
if (this.key.type === "public") return subtle.exportKey("spki", this.key);
|
|
45
|
+
return subtle.exportKey("raw", this.key);
|
|
46
|
+
}
|
|
47
|
+
async toUint8Array() {
|
|
48
|
+
const arrayBuffer = await this.toArrayBuffer();
|
|
49
|
+
return new Uint8Array(arrayBuffer);
|
|
50
|
+
}
|
|
51
|
+
async toBase64() {
|
|
52
|
+
return arrayBufferToBase64(await this.toArrayBuffer());
|
|
53
|
+
}
|
|
54
|
+
async toJWK() {
|
|
55
|
+
return subtle.exportKey("jwk", this.key);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/crypto/key/asymmetric/helpers/wrap.ts
|
|
60
|
+
function enc(type, input) {
|
|
61
|
+
return `-----BEGIN ${type}-----\n${input}\n-----END ${type}-----`;
|
|
77
62
|
}
|
|
78
63
|
function encodePKCS8ToPEM(base64) {
|
|
79
|
-
|
|
64
|
+
return enc("PRIVATE KEY", base64);
|
|
80
65
|
}
|
|
81
66
|
function encodeSPKIToPem(input) {
|
|
82
|
-
|
|
67
|
+
return enc("PUBLIC KEY", input);
|
|
83
68
|
}
|
|
84
|
-
// ------------------------------------------------------------
|
|
85
69
|
function dec(type, input) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
70
|
+
input = input.replace(`-----BEGIN ${type}-----\n`, "");
|
|
71
|
+
input = input.replace(`\n-----END ${type}-----\n`, "");
|
|
72
|
+
input = input.replace(`-----END ${type}-----\n`, "");
|
|
73
|
+
input = input.replace(`\n-----END ${type}-----`, "");
|
|
74
|
+
return input;
|
|
91
75
|
}
|
|
92
76
|
function decodePemToPKCS8(input) {
|
|
93
|
-
|
|
77
|
+
return dec("PRIVATE KEY", input);
|
|
94
78
|
}
|
|
95
79
|
function decodePemToSpki(input) {
|
|
96
|
-
|
|
80
|
+
return dec("PUBLIC KEY", input);
|
|
97
81
|
}
|
|
98
|
-
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/crypto/key/asymmetric/key-usages.ts
|
|
99
84
|
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
return [
|
|
123
|
-
'deriveKey',
|
|
124
|
-
'deriveBits'
|
|
125
|
-
];
|
|
126
|
-
}
|
|
127
|
-
if (name === CryptoAsymmetricAlgorithm.RSA_OAEP) {
|
|
128
|
-
if (format === 'spki') {
|
|
129
|
-
return [
|
|
130
|
-
'encrypt'
|
|
131
|
-
];
|
|
132
|
-
}
|
|
133
|
-
if (format === 'pkcs8') {
|
|
134
|
-
return [
|
|
135
|
-
'decrypt'
|
|
136
|
-
];
|
|
137
|
-
}
|
|
138
|
-
return [
|
|
139
|
-
'encrypt',
|
|
140
|
-
'decrypt'
|
|
141
|
-
];
|
|
142
|
-
}
|
|
143
|
-
throw new SyntaxError(`Key usages can not be determined for asymmetric algorithm: ${name}`);
|
|
144
|
-
}
|
|
145
|
-
|
|
85
|
+
* @see https://nodejs.org/api/webcrypto.html#cryptokeyusages
|
|
86
|
+
*/
|
|
87
|
+
function getKeyUsagesForAsymmetricAlgorithm(name, format) {
|
|
88
|
+
if (name === CryptoAsymmetricAlgorithm.RSA_PSS || name === CryptoAsymmetricAlgorithm.ECDSA || name === CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5) {
|
|
89
|
+
if (format === "spki") return ["verify"];
|
|
90
|
+
if (format === "pkcs8") return ["sign"];
|
|
91
|
+
return ["sign", "verify"];
|
|
92
|
+
}
|
|
93
|
+
if (name === CryptoAsymmetricAlgorithm.ECDH) {
|
|
94
|
+
if (format === "spki") return [];
|
|
95
|
+
return ["deriveKey", "deriveBits"];
|
|
96
|
+
}
|
|
97
|
+
if (name === CryptoAsymmetricAlgorithm.RSA_OAEP) {
|
|
98
|
+
if (format === "spki") return ["encrypt"];
|
|
99
|
+
if (format === "pkcs8") return ["decrypt"];
|
|
100
|
+
return ["encrypt", "decrypt"];
|
|
101
|
+
}
|
|
102
|
+
throw new SyntaxError(`Key usages can not be determined for asymmetric algorithm: ${name}`);
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/crypto/key/asymmetric/normalize.ts
|
|
146
106
|
function normalizeAsymmetricKeyPairCreateOptions(options) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
...options
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return optionsNormalized;
|
|
107
|
+
let optionsNormalized;
|
|
108
|
+
switch (options.name) {
|
|
109
|
+
case CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5:
|
|
110
|
+
case CryptoAsymmetricAlgorithm.RSA_PSS:
|
|
111
|
+
case CryptoAsymmetricAlgorithm.RSA_OAEP:
|
|
112
|
+
optionsNormalized = {
|
|
113
|
+
modulusLength: 2048,
|
|
114
|
+
publicExponent: new Uint8Array([
|
|
115
|
+
1,
|
|
116
|
+
0,
|
|
117
|
+
1
|
|
118
|
+
]),
|
|
119
|
+
hash: "SHA-256",
|
|
120
|
+
...options
|
|
121
|
+
};
|
|
122
|
+
break;
|
|
123
|
+
case CryptoAsymmetricAlgorithm.ECDSA:
|
|
124
|
+
case CryptoAsymmetricAlgorithm.ECDH: optionsNormalized = {
|
|
125
|
+
namedCurve: "P-256",
|
|
126
|
+
...options
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return optionsNormalized;
|
|
175
130
|
}
|
|
176
131
|
function normalizeAsymmetricKeyImportOptions(options) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
if (alg === JWTAlgorithm.ES256) {
|
|
258
|
-
return {
|
|
259
|
-
name: CryptoAsymmetricAlgorithm.ECDSA,
|
|
260
|
-
namedCurve: 'P-256'
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
if (alg === JWTAlgorithm.ES384) {
|
|
264
|
-
return {
|
|
265
|
-
name: CryptoAsymmetricAlgorithm.ECDSA,
|
|
266
|
-
namedCurve: 'P-384'
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
if (alg === JWTAlgorithm.ES512) {
|
|
270
|
-
return {
|
|
271
|
-
name: CryptoAsymmetricAlgorithm.ECDSA,
|
|
272
|
-
namedCurve: 'P-521'
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
throw new Error(`Signature algorithm ${alg} is not supported.`);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
132
|
+
let optionsNormalized;
|
|
133
|
+
switch (options.name) {
|
|
134
|
+
case CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5:
|
|
135
|
+
case CryptoAsymmetricAlgorithm.RSA_PSS:
|
|
136
|
+
case CryptoAsymmetricAlgorithm.RSA_OAEP:
|
|
137
|
+
optionsNormalized = {
|
|
138
|
+
hash: "SHA-256",
|
|
139
|
+
...options
|
|
140
|
+
};
|
|
141
|
+
break;
|
|
142
|
+
case CryptoAsymmetricAlgorithm.ECDSA:
|
|
143
|
+
case CryptoAsymmetricAlgorithm.ECDH: optionsNormalized = {
|
|
144
|
+
namedCurve: "P-256",
|
|
145
|
+
...options
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return optionsNormalized;
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/crypto/key/asymmetric/module.ts
|
|
152
|
+
var AsymmetricKey = class AsymmetricKey extends BaseKey {
|
|
153
|
+
async toPem() {
|
|
154
|
+
const base64 = await this.toBase64();
|
|
155
|
+
if (this.key.type === "public") return encodeSPKIToPem(base64);
|
|
156
|
+
if (this.key.type === "private") return encodePKCS8ToPEM(base64);
|
|
157
|
+
throw new Error(`${this.key.type} can not be converted to pem.`);
|
|
158
|
+
}
|
|
159
|
+
static async fromPem(ctx) {
|
|
160
|
+
if (ctx.format === "pkcs8") return AsymmetricKey.fromBase64({
|
|
161
|
+
...ctx,
|
|
162
|
+
key: decodePemToPKCS8(ctx.key)
|
|
163
|
+
});
|
|
164
|
+
return AsymmetricKey.fromBase64({
|
|
165
|
+
...ctx,
|
|
166
|
+
key: decodePemToSpki(ctx.key)
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
static async fromBase64(ctx) {
|
|
170
|
+
const arrayBuffer = base64ToArrayBuffer(ctx.key);
|
|
171
|
+
return AsymmetricKey.fromArrayBuffer({
|
|
172
|
+
...ctx,
|
|
173
|
+
key: arrayBuffer
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
static async fromArrayBuffer(ctx) {
|
|
177
|
+
const normalizedOptions = normalizeAsymmetricKeyImportOptions(ctx.options);
|
|
178
|
+
return new AsymmetricKey(await subtle.importKey(ctx.format, ctx.key, normalizedOptions, true, getKeyUsagesForAsymmetricAlgorithm(normalizedOptions.name, ctx.format)));
|
|
179
|
+
}
|
|
180
|
+
static buildImportOptionsForJWTAlgorithm(alg) {
|
|
181
|
+
if (alg === JWTAlgorithm.RS256) return {
|
|
182
|
+
name: CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5,
|
|
183
|
+
hash: "SHA-256"
|
|
184
|
+
};
|
|
185
|
+
if (alg === JWTAlgorithm.RS384) return {
|
|
186
|
+
name: CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5,
|
|
187
|
+
hash: "SHA-384"
|
|
188
|
+
};
|
|
189
|
+
if (alg === JWTAlgorithm.RS512) return {
|
|
190
|
+
name: CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5,
|
|
191
|
+
hash: "SHA-512"
|
|
192
|
+
};
|
|
193
|
+
if (alg === JWTAlgorithm.ES256) return {
|
|
194
|
+
name: CryptoAsymmetricAlgorithm.ECDSA,
|
|
195
|
+
namedCurve: "P-256"
|
|
196
|
+
};
|
|
197
|
+
if (alg === JWTAlgorithm.ES384) return {
|
|
198
|
+
name: CryptoAsymmetricAlgorithm.ECDSA,
|
|
199
|
+
namedCurve: "P-384"
|
|
200
|
+
};
|
|
201
|
+
if (alg === JWTAlgorithm.ES512) return {
|
|
202
|
+
name: CryptoAsymmetricAlgorithm.ECDSA,
|
|
203
|
+
namedCurve: "P-521"
|
|
204
|
+
};
|
|
205
|
+
throw new Error(`Signature algorithm ${alg} is not supported.`);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/crypto/key/asymmetric/check.ts
|
|
279
210
|
function isAsymmetricAlgorithm(input) {
|
|
280
|
-
|
|
211
|
+
return Object.values(CryptoAsymmetricAlgorithm).includes(input);
|
|
281
212
|
}
|
|
282
|
-
|
|
213
|
+
//#endregion
|
|
214
|
+
//#region src/crypto/key/asymmetric/create.ts
|
|
283
215
|
async function createAsymmetricKeyPair(options) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
SymmetricAlgorithm["AES_CTR"] = "AES-CTR";
|
|
296
|
-
SymmetricAlgorithm["AES_CBC"] = "AES-CBC";
|
|
297
|
-
SymmetricAlgorithm["AES_GCM"] = "AES-GCM";
|
|
298
|
-
return SymmetricAlgorithm;
|
|
216
|
+
const optionsNormalized = normalizeAsymmetricKeyPairCreateOptions(options);
|
|
217
|
+
return subtle.generateKey(optionsNormalized, true, getKeyUsagesForAsymmetricAlgorithm(optionsNormalized.name));
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/crypto/key/symmetric/constants.ts
|
|
221
|
+
let SymmetricAlgorithm = /* @__PURE__ */ function(SymmetricAlgorithm) {
|
|
222
|
+
SymmetricAlgorithm["HMAC"] = "HMAC";
|
|
223
|
+
SymmetricAlgorithm["AES_CTR"] = "AES-CTR";
|
|
224
|
+
SymmetricAlgorithm["AES_CBC"] = "AES-CBC";
|
|
225
|
+
SymmetricAlgorithm["AES_GCM"] = "AES-GCM";
|
|
226
|
+
return SymmetricAlgorithm;
|
|
299
227
|
}({});
|
|
300
|
-
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/crypto/key/symmetric/check.ts
|
|
301
230
|
function isSymmetricAlgorithm(input) {
|
|
302
|
-
|
|
231
|
+
return Object.values(SymmetricAlgorithm).includes(input);
|
|
303
232
|
}
|
|
304
|
-
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region src/crypto/key/symmetric/key-usages.ts
|
|
305
235
|
function getKeyUsagesForSymmetricAlgorithm(name) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
return [
|
|
316
|
-
'encrypt',
|
|
317
|
-
'decrypt'
|
|
318
|
-
];
|
|
319
|
-
}
|
|
320
|
-
throw new SyntaxError(`Key usages can not be determined for symmetric algorithm: ${name}`);
|
|
321
|
-
}
|
|
322
|
-
|
|
236
|
+
/**
|
|
237
|
+
* @see https://nodejs.org/api/webcrypto.html#cryptokeyusages
|
|
238
|
+
*/
|
|
239
|
+
if (name === SymmetricAlgorithm.HMAC) return ["sign", "verify"];
|
|
240
|
+
if (name === SymmetricAlgorithm.AES_CBC || name === SymmetricAlgorithm.AES_GCM || name === SymmetricAlgorithm.AES_CTR) return ["encrypt", "decrypt"];
|
|
241
|
+
throw new SyntaxError(`Key usages can not be determined for symmetric algorithm: ${name}`);
|
|
242
|
+
}
|
|
243
|
+
//#endregion
|
|
244
|
+
//#region src/crypto/key/symmetric/normalize.ts
|
|
323
245
|
function normalizeSymmetricKeyCreateOptions(input) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
name: input.name
|
|
333
|
-
};
|
|
246
|
+
if (input.name === SymmetricAlgorithm.HMAC) return {
|
|
247
|
+
hash: "SHA-256",
|
|
248
|
+
...input
|
|
249
|
+
};
|
|
250
|
+
return {
|
|
251
|
+
length: 256,
|
|
252
|
+
name: input.name
|
|
253
|
+
};
|
|
334
254
|
}
|
|
335
255
|
function normalizeSymmetricKeyImportOptions(input) {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
hash: 'SHA-512'
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
throw new Error(`Signature algorithm ${alg} is not supported.`);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
256
|
+
if (input.name === SymmetricAlgorithm.HMAC) return {
|
|
257
|
+
hash: "SHA-256",
|
|
258
|
+
...input
|
|
259
|
+
};
|
|
260
|
+
return input;
|
|
261
|
+
}
|
|
262
|
+
//#endregion
|
|
263
|
+
//#region src/crypto/key/symmetric/module.ts
|
|
264
|
+
var SymmetricKey = class SymmetricKey extends BaseKey {
|
|
265
|
+
static async fromBase64(ctx) {
|
|
266
|
+
const arrayBuffer = base64ToArrayBuffer(ctx.key);
|
|
267
|
+
return SymmetricKey.fromArrayBuffer({
|
|
268
|
+
...ctx,
|
|
269
|
+
key: arrayBuffer
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
static async fromArrayBuffer(ctx) {
|
|
273
|
+
const normalizedOptions = normalizeSymmetricKeyImportOptions(ctx.options);
|
|
274
|
+
return new SymmetricKey(await subtle.importKey(ctx.format, ctx.key, normalizedOptions, true, getKeyUsagesForSymmetricAlgorithm(normalizedOptions.name)));
|
|
275
|
+
}
|
|
276
|
+
static buildImportOptionsForJWTAlgorithm(alg) {
|
|
277
|
+
if (alg === JWTAlgorithm.HS256) return {
|
|
278
|
+
name: SymmetricAlgorithm.HMAC,
|
|
279
|
+
hash: "SHA-256"
|
|
280
|
+
};
|
|
281
|
+
if (alg === JWTAlgorithm.HS384) return {
|
|
282
|
+
name: SymmetricAlgorithm.HMAC,
|
|
283
|
+
hash: "SHA-384"
|
|
284
|
+
};
|
|
285
|
+
if (alg === JWTAlgorithm.HS512) return {
|
|
286
|
+
name: SymmetricAlgorithm.HMAC,
|
|
287
|
+
hash: "SHA-512"
|
|
288
|
+
};
|
|
289
|
+
throw new Error(`Signature algorithm ${alg} is not supported.`);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
//#endregion
|
|
293
|
+
//#region src/crypto/key/symmetric/create.ts
|
|
381
294
|
async function createSymmetricKey(input) {
|
|
382
|
-
|
|
383
|
-
|
|
295
|
+
const optionsNormalized = normalizeSymmetricKeyCreateOptions(input);
|
|
296
|
+
return subtle.generateKey(optionsNormalized, true, getKeyUsagesForSymmetricAlgorithm(optionsNormalized.name));
|
|
384
297
|
}
|
|
385
|
-
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/crypto/json-web-token/extract.ts
|
|
386
300
|
/**
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
typ: 'JWT',
|
|
404
|
-
alg: transformInternalToJWTAlgorithm(header.algorithm),
|
|
405
|
-
cty: header.contentType,
|
|
406
|
-
jku: header.jsonKeyUrl,
|
|
407
|
-
kid: header.keyId,
|
|
408
|
-
x5u: header.x5Url,
|
|
409
|
-
x5c: header.x5CertChain,
|
|
410
|
-
x5t: header.x5CertThumbprint,
|
|
411
|
-
'x5t#S256': header.x5TS256CertThumbprint,
|
|
412
|
-
};
|
|
413
|
-
*/ } catch {
|
|
414
|
-
throw JWTError.headerInvalid('The token header could not be extracted.');
|
|
415
|
-
}
|
|
301
|
+
* Decode a JWT token with no verification.
|
|
302
|
+
*
|
|
303
|
+
* @param token
|
|
304
|
+
*
|
|
305
|
+
* @throws JWTError
|
|
306
|
+
*/
|
|
307
|
+
function extractTokenHeader(token) {
|
|
308
|
+
const parts = token.split(".");
|
|
309
|
+
if (parts.length !== 3) throw JWTError.invalid();
|
|
310
|
+
const [headerBase64] = parts;
|
|
311
|
+
try {
|
|
312
|
+
const payload = atob(headerBase64);
|
|
313
|
+
return JSON.parse(payload);
|
|
314
|
+
} catch {
|
|
315
|
+
throw JWTError.headerInvalid("The token header could not be extracted.");
|
|
316
|
+
}
|
|
416
317
|
}
|
|
417
318
|
/**
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
319
|
+
* @param token
|
|
320
|
+
*
|
|
321
|
+
* @throws JWTError
|
|
322
|
+
*/
|
|
323
|
+
function extractTokenPayload(token) {
|
|
324
|
+
const parts = token.split(".");
|
|
325
|
+
if (parts.length !== 3) throw JWTError.invalid();
|
|
326
|
+
const [, payloadBase64] = parts;
|
|
327
|
+
try {
|
|
328
|
+
const payload = atob(payloadBase64);
|
|
329
|
+
return JSON.parse(payload);
|
|
330
|
+
} catch {
|
|
331
|
+
throw JWTError.payloadInvalid("The token payload could not be extracted.");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/crypto/json-web-token/utils.ts
|
|
435
336
|
function createErrorForJWTError(e) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
}
|
|
459
|
-
// @see https://github.com/Keats/jsonwebtoken/blob/master/src/errors.rs
|
|
460
|
-
switch(e.message){
|
|
461
|
-
case 'ExpiredSignature':
|
|
462
|
-
{
|
|
463
|
-
return JWTError.expired();
|
|
464
|
-
}
|
|
465
|
-
case 'ImmatureSignature':
|
|
466
|
-
{
|
|
467
|
-
return JWTError.notActiveBefore();
|
|
468
|
-
}
|
|
469
|
-
case 'InvalidToken':
|
|
470
|
-
case 'InvalidSignature':
|
|
471
|
-
{
|
|
472
|
-
return JWTError.payloadInvalid();
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
return new JWTError({
|
|
477
|
-
cause: e,
|
|
478
|
-
logMessage: true,
|
|
479
|
-
message: 'The JWT error could not be determined.'
|
|
480
|
-
});
|
|
337
|
+
if (isObject$1(e)) {
|
|
338
|
+
if (typeof e.name === "string") switch (e.name) {
|
|
339
|
+
case "TokenExpiredError": return JWTError.expired();
|
|
340
|
+
case "NotBeforeError":
|
|
341
|
+
if (typeof e.date === "string" || e.date instanceof Date) return JWTError.notActiveBefore(e.date);
|
|
342
|
+
break;
|
|
343
|
+
case "JsonWebTokenError":
|
|
344
|
+
if (typeof e.message === "string") return JWTError.payloadInvalid(e.message);
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
switch (e.message) {
|
|
348
|
+
case "ExpiredSignature": return JWTError.expired();
|
|
349
|
+
case "ImmatureSignature": return JWTError.notActiveBefore();
|
|
350
|
+
case "InvalidToken":
|
|
351
|
+
case "InvalidSignature": return JWTError.payloadInvalid();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return new JWTError({
|
|
355
|
+
cause: e,
|
|
356
|
+
logMessage: true,
|
|
357
|
+
message: "The JWT error could not be determined."
|
|
358
|
+
});
|
|
481
359
|
}
|
|
482
360
|
function transformJWTAlgorithmToInternal(algorithm) {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
{
|
|
502
|
-
return Algorithm.RS384;
|
|
503
|
-
}
|
|
504
|
-
case JWTAlgorithm.RS512:
|
|
505
|
-
{
|
|
506
|
-
return Algorithm.RS512;
|
|
507
|
-
}
|
|
508
|
-
case JWTAlgorithm.ES256:
|
|
509
|
-
{
|
|
510
|
-
return Algorithm.ES256;
|
|
511
|
-
}
|
|
512
|
-
case JWTAlgorithm.ES384:
|
|
513
|
-
{
|
|
514
|
-
return Algorithm.ES384;
|
|
515
|
-
}
|
|
516
|
-
case JWTAlgorithm.PS256:
|
|
517
|
-
{
|
|
518
|
-
return Algorithm.PS256;
|
|
519
|
-
}
|
|
520
|
-
case JWTAlgorithm.PS384:
|
|
521
|
-
{
|
|
522
|
-
return Algorithm.PS384;
|
|
523
|
-
}
|
|
524
|
-
case JWTAlgorithm.PS512:
|
|
525
|
-
{
|
|
526
|
-
return Algorithm.PS512;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
throw new Error(`The algorithm ${algorithm} is not supported.`);
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
const getUtcTimestamp = ()=>Math.floor(new Date().getTime() / 1000);
|
|
361
|
+
switch (algorithm) {
|
|
362
|
+
case JWTAlgorithm.HS256: return Algorithm.HS256;
|
|
363
|
+
case JWTAlgorithm.HS384: return Algorithm.HS384;
|
|
364
|
+
case JWTAlgorithm.HS512: return Algorithm.HS512;
|
|
365
|
+
case JWTAlgorithm.RS256: return Algorithm.RS256;
|
|
366
|
+
case JWTAlgorithm.RS384: return Algorithm.RS384;
|
|
367
|
+
case JWTAlgorithm.RS512: return Algorithm.RS512;
|
|
368
|
+
case JWTAlgorithm.ES256: return Algorithm.ES256;
|
|
369
|
+
case JWTAlgorithm.ES384: return Algorithm.ES384;
|
|
370
|
+
case JWTAlgorithm.PS256: return Algorithm.PS256;
|
|
371
|
+
case JWTAlgorithm.PS384: return Algorithm.PS384;
|
|
372
|
+
case JWTAlgorithm.PS512: return Algorithm.PS512;
|
|
373
|
+
}
|
|
374
|
+
throw new Error(`The algorithm ${algorithm} is not supported.`);
|
|
375
|
+
}
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region src/crypto/json-web-token/sign/module.ts
|
|
378
|
+
const getUtcTimestamp = () => Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3);
|
|
533
379
|
async function signToken(claims, context) {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
let key;
|
|
566
|
-
if (typeof context.key === 'string') {
|
|
567
|
-
key = context.key;
|
|
568
|
-
} else {
|
|
569
|
-
const keyContainer = new SymmetricKey(context.key);
|
|
570
|
-
key = await keyContainer.toUint8Array();
|
|
571
|
-
}
|
|
572
|
-
return sign(claims, key, {
|
|
573
|
-
algorithm,
|
|
574
|
-
keyId: context.keyId
|
|
575
|
-
});
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
throw new JWTError();
|
|
579
|
-
}
|
|
580
|
-
|
|
380
|
+
if (typeof claims.exp !== "number") claims.exp = getUtcTimestamp() + 3600;
|
|
381
|
+
if (typeof claims.iat !== "number") claims.iat = getUtcTimestamp();
|
|
382
|
+
switch (context.type) {
|
|
383
|
+
case JWKType.RSA:
|
|
384
|
+
case JWKType.EC: {
|
|
385
|
+
let algorithm;
|
|
386
|
+
let key;
|
|
387
|
+
if (typeof context.key === "string") key = encodePKCS8ToPEM(context.key);
|
|
388
|
+
else key = await new AsymmetricKey(context.key).toPem();
|
|
389
|
+
if (context.type === JWKType.RSA) algorithm = context.algorithm ? transformJWTAlgorithmToInternal(context.algorithm) : Algorithm.RS256;
|
|
390
|
+
else algorithm = context.algorithm ? transformJWTAlgorithmToInternal(context.algorithm) : Algorithm.ES256;
|
|
391
|
+
return sign(claims, key, {
|
|
392
|
+
algorithm,
|
|
393
|
+
keyId: context.keyId
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
case JWKType.OCT: {
|
|
397
|
+
const algorithm = context.algorithm ? transformJWTAlgorithmToInternal(context.algorithm) : Algorithm.HS256;
|
|
398
|
+
let key;
|
|
399
|
+
if (typeof context.key === "string") key = context.key;
|
|
400
|
+
else key = await new SymmetricKey(context.key).toUint8Array();
|
|
401
|
+
return sign(claims, key, {
|
|
402
|
+
algorithm,
|
|
403
|
+
keyId: context.keyId
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
throw new JWTError();
|
|
408
|
+
}
|
|
409
|
+
//#endregion
|
|
410
|
+
//#region src/crypto/json-web-token/verify/module.ts
|
|
581
411
|
/**
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
709
|
-
async set(key, value, options) {
|
|
710
|
-
this.instance.set(key, value, {
|
|
711
|
-
ttl: options.ttl
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
|
-
async drop(key) {
|
|
715
|
-
this.instance.delete(key);
|
|
716
|
-
}
|
|
717
|
-
async dropMany(keys) {
|
|
718
|
-
for (const key of keys){
|
|
719
|
-
this.instance.delete(key);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
async clear(options = {}) {
|
|
723
|
-
if (options.prefix) {
|
|
724
|
-
const keys = this.instance.keys();
|
|
725
|
-
let iterator = keys.next();
|
|
726
|
-
while(!iterator.done){
|
|
727
|
-
if (typeof iterator.value !== 'string') {
|
|
728
|
-
continue;
|
|
729
|
-
}
|
|
730
|
-
if (iterator.value.startsWith(options.prefix)) {
|
|
731
|
-
this.instance.delete(iterator.value);
|
|
732
|
-
}
|
|
733
|
-
iterator = keys.next();
|
|
734
|
-
}
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
this.instance.clear();
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
|
|
412
|
+
* Verify JWT.
|
|
413
|
+
*
|
|
414
|
+
* @param token
|
|
415
|
+
* @param context
|
|
416
|
+
*
|
|
417
|
+
* @throws OAuth2Error
|
|
418
|
+
*/
|
|
419
|
+
async function verifyToken(token, context) {
|
|
420
|
+
let promise;
|
|
421
|
+
let output;
|
|
422
|
+
try {
|
|
423
|
+
switch (context.type) {
|
|
424
|
+
case JWKType.RSA:
|
|
425
|
+
case JWKType.EC: {
|
|
426
|
+
let algorithms;
|
|
427
|
+
if (context.type === JWKType.RSA) algorithms = context.algorithms ? context.algorithms.map((algorithm) => transformJWTAlgorithmToInternal(algorithm)) : [
|
|
428
|
+
Algorithm.RS256,
|
|
429
|
+
Algorithm.RS384,
|
|
430
|
+
Algorithm.RS512,
|
|
431
|
+
Algorithm.PS256,
|
|
432
|
+
Algorithm.PS384,
|
|
433
|
+
Algorithm.PS512
|
|
434
|
+
];
|
|
435
|
+
else algorithms = context.algorithms ? context.algorithms.map((algorithm) => transformJWTAlgorithmToInternal(algorithm)) : [Algorithm.ES256, Algorithm.ES384];
|
|
436
|
+
let key;
|
|
437
|
+
if (typeof context.key === "string") key = encodeSPKIToPem(context.key);
|
|
438
|
+
else key = await new AsymmetricKey(context.key).toPem();
|
|
439
|
+
promise = verify(token, key, {
|
|
440
|
+
algorithms,
|
|
441
|
+
validateNbf: true
|
|
442
|
+
});
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
case JWKType.OCT: {
|
|
446
|
+
const algorithms = context.algorithms ? context.algorithms.map((algorithm) => transformJWTAlgorithmToInternal(algorithm)) : [
|
|
447
|
+
Algorithm.HS256,
|
|
448
|
+
Algorithm.HS384,
|
|
449
|
+
Algorithm.HS512
|
|
450
|
+
];
|
|
451
|
+
let key;
|
|
452
|
+
if (typeof context.key === "string") key = context.key;
|
|
453
|
+
else key = await new SymmetricKey(context.key).toUint8Array();
|
|
454
|
+
promise = verify(token, key, {
|
|
455
|
+
algorithms,
|
|
456
|
+
validateNbf: true
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (promise) output = await promise;
|
|
461
|
+
} catch (e) {
|
|
462
|
+
throw createErrorForJWTError(e);
|
|
463
|
+
}
|
|
464
|
+
if (!output) throw new JWTError();
|
|
465
|
+
return output;
|
|
466
|
+
}
|
|
467
|
+
//#endregion
|
|
468
|
+
//#region src/domain-event/module.ts
|
|
469
|
+
var DomainEventPublisher = class {
|
|
470
|
+
publishers;
|
|
471
|
+
constructor() {
|
|
472
|
+
this.publishers = /* @__PURE__ */ new Set();
|
|
473
|
+
}
|
|
474
|
+
mount(publisher) {
|
|
475
|
+
this.publishers.add(publisher);
|
|
476
|
+
}
|
|
477
|
+
async publish(ctx) {
|
|
478
|
+
const publishers = this.publishers.values();
|
|
479
|
+
while (true) {
|
|
480
|
+
const it = publishers.next();
|
|
481
|
+
if (it.done) return;
|
|
482
|
+
await it.value.publish(ctx);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region src/services/cache/adapters/memory.ts
|
|
488
|
+
var MemoryCache = class {
|
|
489
|
+
instance;
|
|
490
|
+
constructor(options = {}) {
|
|
491
|
+
this.instance = new TTLCache({
|
|
492
|
+
checkAgeOnGet: true,
|
|
493
|
+
ttl: Infinity,
|
|
494
|
+
...options || {}
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
async pop(key) {
|
|
498
|
+
if (this.instance.has(key)) {
|
|
499
|
+
const output = this.instance.get(key);
|
|
500
|
+
this.instance.delete(key);
|
|
501
|
+
return output;
|
|
502
|
+
}
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
async has(key) {
|
|
506
|
+
return this.instance.has(key);
|
|
507
|
+
}
|
|
508
|
+
async get(key) {
|
|
509
|
+
const output = await this.instance.get(key);
|
|
510
|
+
if (output) return output;
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
async set(key, value, options) {
|
|
514
|
+
this.instance.set(key, value, { ttl: options.ttl });
|
|
515
|
+
}
|
|
516
|
+
async drop(key) {
|
|
517
|
+
this.instance.delete(key);
|
|
518
|
+
}
|
|
519
|
+
async dropMany(keys) {
|
|
520
|
+
for (const key of keys) this.instance.delete(key);
|
|
521
|
+
}
|
|
522
|
+
async clear(options = {}) {
|
|
523
|
+
if (options.prefix) {
|
|
524
|
+
const keys = this.instance.keys();
|
|
525
|
+
let iterator = keys.next();
|
|
526
|
+
while (!iterator.done) {
|
|
527
|
+
if (typeof iterator.value !== "string") continue;
|
|
528
|
+
if (iterator.value.startsWith(options.prefix)) this.instance.delete(iterator.value);
|
|
529
|
+
iterator = keys.next();
|
|
530
|
+
}
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
this.instance.clear();
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/services/redis/check.ts
|
|
741
538
|
function isRedisClient(data) {
|
|
742
|
-
|
|
539
|
+
return isObject$1(data) && typeof data.connect === "function" && typeof data.disconnect === "function";
|
|
743
540
|
}
|
|
744
|
-
|
|
541
|
+
//#endregion
|
|
542
|
+
//#region src/services/redis/factory.ts
|
|
745
543
|
function createRedisClient(input) {
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
async dropMany(keys) {
|
|
802
|
-
const pipeline = this.client.pipeline();
|
|
803
|
-
for (const key of keys){
|
|
804
|
-
pipeline.del(key);
|
|
805
|
-
}
|
|
806
|
-
await pipeline.exec();
|
|
807
|
-
}
|
|
808
|
-
async clear(options = {}) {
|
|
809
|
-
if (options.prefix) {
|
|
810
|
-
const pipeline = this.client.pipeline();
|
|
811
|
-
const keys = await this.client.keys(`${options.prefix}*`);
|
|
812
|
-
for (const key of keys){
|
|
813
|
-
pipeline.del(key);
|
|
814
|
-
}
|
|
815
|
-
await pipeline.exec();
|
|
816
|
-
return;
|
|
817
|
-
}
|
|
818
|
-
await this.client.flushdb();
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
544
|
+
if (typeof input === "boolean") return createClient({ connectionString: "redis://127.0.0.1" });
|
|
545
|
+
if (typeof input === "string") return createClient({ connectionString: input });
|
|
546
|
+
if (!isRedisClient(input)) return createClient({ options: input });
|
|
547
|
+
return input;
|
|
548
|
+
}
|
|
549
|
+
//#endregion
|
|
550
|
+
//#region src/services/cache/adapters/redis.ts
|
|
551
|
+
var RedisCache = class {
|
|
552
|
+
client;
|
|
553
|
+
jsonAdapter;
|
|
554
|
+
constructor(input) {
|
|
555
|
+
this.client = createRedisClient(input);
|
|
556
|
+
this.jsonAdapter = new JsonAdapter(this.client);
|
|
557
|
+
}
|
|
558
|
+
async get(key) {
|
|
559
|
+
const output = await this.jsonAdapter.get(key);
|
|
560
|
+
if (output) return output;
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
async pop(key) {
|
|
564
|
+
const raw = await this.client.getdel(key);
|
|
565
|
+
if (!raw) return null;
|
|
566
|
+
try {
|
|
567
|
+
return JSON.parse(raw);
|
|
568
|
+
} catch {
|
|
569
|
+
return null;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
async has(key) {
|
|
573
|
+
return !!await this.get(key);
|
|
574
|
+
}
|
|
575
|
+
async set(key, value, options) {
|
|
576
|
+
await this.jsonAdapter.set(key, value, { milliseconds: options.ttl });
|
|
577
|
+
}
|
|
578
|
+
async drop(key) {
|
|
579
|
+
await this.jsonAdapter.drop(key);
|
|
580
|
+
}
|
|
581
|
+
async dropMany(keys) {
|
|
582
|
+
const pipeline = this.client.pipeline();
|
|
583
|
+
for (const key of keys) pipeline.del(key);
|
|
584
|
+
await pipeline.exec();
|
|
585
|
+
}
|
|
586
|
+
async clear(options = {}) {
|
|
587
|
+
if (options.prefix) {
|
|
588
|
+
const pipeline = this.client.pipeline();
|
|
589
|
+
const keys = await this.client.keys(`${options.prefix}*`);
|
|
590
|
+
for (const key of keys) pipeline.del(key);
|
|
591
|
+
await pipeline.exec();
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
await this.client.flushdb();
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
//#endregion
|
|
598
|
+
//#region src/services/cache/helper.ts
|
|
822
599
|
function buildCacheKey(options) {
|
|
823
|
-
|
|
600
|
+
return buildRedisKeyPath(options);
|
|
824
601
|
}
|
|
825
|
-
|
|
602
|
+
//#endregion
|
|
603
|
+
//#region src/services/logger/module.ts
|
|
826
604
|
function createNoopLogger() {
|
|
827
|
-
|
|
828
|
-
silent: true
|
|
829
|
-
});
|
|
605
|
+
return createLogger$1({ silent: true });
|
|
830
606
|
}
|
|
831
607
|
function createLogger(context) {
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
}
|
|
859
|
-
// @see https://github.com/winstonjs/triple-beam/blob/master/config/npm.js
|
|
860
|
-
return createLogger$1({
|
|
861
|
-
format: format.combine(format.errors({
|
|
862
|
-
stack: true
|
|
863
|
-
}), format.timestamp(), format.colorize(), format.simple()),
|
|
864
|
-
transports: items
|
|
865
|
-
});
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
const instance$1 = singa({
|
|
869
|
-
name: 'logger'
|
|
870
|
-
});
|
|
608
|
+
let items;
|
|
609
|
+
const cwd = context.directory || process.cwd();
|
|
610
|
+
if (context.env === "production") items = [
|
|
611
|
+
new transports.Console({ level: "info" }),
|
|
612
|
+
new transports.File({
|
|
613
|
+
filename: path.join(cwd, "http.log"),
|
|
614
|
+
level: "http",
|
|
615
|
+
maxsize: 10 * 1024 * 1024,
|
|
616
|
+
maxFiles: 5
|
|
617
|
+
}),
|
|
618
|
+
new transports.File({
|
|
619
|
+
filename: path.join(cwd, "error.log"),
|
|
620
|
+
level: "warn",
|
|
621
|
+
maxsize: 10 * 1024 * 1024,
|
|
622
|
+
maxFiles: 5
|
|
623
|
+
})
|
|
624
|
+
];
|
|
625
|
+
else items = [new transports.Console({ level: "debug" })];
|
|
626
|
+
return createLogger$1({
|
|
627
|
+
format: format.combine(format.errors({ stack: true }), format.timestamp(), format.colorize(), format.simple()),
|
|
628
|
+
transports: items
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
//#endregion
|
|
632
|
+
//#region src/services/logger/singleton.ts
|
|
633
|
+
const instance$1 = singa({ name: "logger" });
|
|
871
634
|
function setLoggerFactory(factory) {
|
|
872
|
-
|
|
635
|
+
instance$1.setFactory(factory);
|
|
873
636
|
}
|
|
874
637
|
function isLoggerUsable() {
|
|
875
|
-
|
|
638
|
+
return instance$1.has() || instance$1.hasFactory();
|
|
876
639
|
}
|
|
877
640
|
function setLogger(input) {
|
|
878
|
-
|
|
641
|
+
instance$1.set(input);
|
|
879
642
|
}
|
|
880
643
|
function useLogger() {
|
|
881
|
-
|
|
644
|
+
return instance$1.use();
|
|
882
645
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
});
|
|
646
|
+
//#endregion
|
|
647
|
+
//#region src/services/vault/singleton.ts
|
|
648
|
+
const instance = singa({ name: "vault" });
|
|
887
649
|
function setVaultFactory(factory) {
|
|
888
|
-
|
|
650
|
+
instance.setFactory(factory);
|
|
889
651
|
}
|
|
890
652
|
function isVaultClientUsable() {
|
|
891
|
-
|
|
653
|
+
return instance.has() || instance.hasFactory();
|
|
892
654
|
}
|
|
893
655
|
function useVaultClient() {
|
|
894
|
-
|
|
656
|
+
return instance.use();
|
|
895
657
|
}
|
|
896
|
-
|
|
658
|
+
//#endregion
|
|
659
|
+
//#region src/domain-event/utils.ts
|
|
897
660
|
function transformDomainEventData(input) {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
input[key] = value.toISOString();
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
return input;
|
|
661
|
+
const keys = Object.keys(input);
|
|
662
|
+
for (const key_ of keys) {
|
|
663
|
+
const key = key_;
|
|
664
|
+
const value = input[key];
|
|
665
|
+
if (!isObject(value)) continue;
|
|
666
|
+
if (value instanceof Date) input[key] = value.toISOString();
|
|
667
|
+
}
|
|
668
|
+
return input;
|
|
910
669
|
}
|
|
911
670
|
function buildDomainEventChannelName(input, id) {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
* Author Peter Placzek (tada5hi)
|
|
981
|
-
* For the full copyright and license information,
|
|
982
|
-
* view the LICENSE file that was distributed with this source code.
|
|
983
|
-
*/ function hasOwnProperty(obj, prop) {
|
|
984
|
-
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
export { AsymmetricKey, BaseKey, CryptoAsymmetricAlgorithm, DomainEventPublisher, DomainEventRedisPublisher, DomainEventSocketPublisher, MemoryCache, RedisCache, SymmetricAlgorithm, SymmetricKey, buildCacheKey, compare, createAsymmetricKeyPair, createLogger, createNoopLogger, createRedisClient, createSymmetricKey, decodePemToPKCS8, decodePemToSpki, encodePKCS8ToPEM, encodeSPKIToPem, extractTokenHeader, extractTokenPayload, getKeyUsagesForAsymmetricAlgorithm, getKeyUsagesForSymmetricAlgorithm, hasOwnProperty, hash, isAsymmetricAlgorithm, isLoggerUsable, isRedisClient, isSymmetricAlgorithm, isVaultClientUsable, normalizeAsymmetricKeyImportOptions, normalizeAsymmetricKeyPairCreateOptions, setLogger, setLoggerFactory, setVaultFactory, signToken, useLogger, useVaultClient, verifyToken };
|
|
988
|
-
//# sourceMappingURL=index.mjs.map
|
|
671
|
+
if (typeof input === "string") return input;
|
|
672
|
+
return input(id);
|
|
673
|
+
}
|
|
674
|
+
//#endregion
|
|
675
|
+
//#region src/domain-event/redis/module.ts
|
|
676
|
+
var DomainEventRedisPublisher = class {
|
|
677
|
+
driver;
|
|
678
|
+
constructor(input) {
|
|
679
|
+
this.driver = createRedisClient(input);
|
|
680
|
+
}
|
|
681
|
+
async publish(ctx) {
|
|
682
|
+
const data = JSON.stringify(transformDomainEventData(ctx.content));
|
|
683
|
+
const pipeline = this.driver.pipeline();
|
|
684
|
+
for (let i = 0; i < ctx.destinations.length; i++) {
|
|
685
|
+
const { namespace } = ctx.destinations[i];
|
|
686
|
+
const keyPrefix = namespace ? `${namespace}:` : "";
|
|
687
|
+
let key = keyPrefix + buildDomainEventChannelName(ctx.destinations[i].channel);
|
|
688
|
+
pipeline.publish(key, data);
|
|
689
|
+
if (typeof ctx.destinations[i].channel === "function") {
|
|
690
|
+
key = keyPrefix + buildDomainEventChannelName(ctx.destinations[i].channel, ctx.content.data.id);
|
|
691
|
+
pipeline.publish(key, data);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
await pipeline.exec();
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
//#endregion
|
|
698
|
+
//#region src/domain-event/socket/module.ts
|
|
699
|
+
var DomainEventSocketPublisher = class {
|
|
700
|
+
driver;
|
|
701
|
+
constructor(input) {
|
|
702
|
+
this.driver = new Emitter(createRedisClient(input));
|
|
703
|
+
}
|
|
704
|
+
async publish(ctx) {
|
|
705
|
+
ctx.content = transformDomainEventData(ctx.content);
|
|
706
|
+
for (let i = 0; i < ctx.destinations.length; i++) {
|
|
707
|
+
const destination = ctx.destinations[i];
|
|
708
|
+
let emitter;
|
|
709
|
+
if (destination.namespace) emitter = this.driver.of(destination.namespace);
|
|
710
|
+
else emitter = this.driver;
|
|
711
|
+
let roomName = buildDomainEventChannelName(destination.channel);
|
|
712
|
+
const fullEventName = buildEventFullName(ctx.content.type, ctx.content.event);
|
|
713
|
+
emitter.in(roomName).emit(fullEventName, {
|
|
714
|
+
...ctx.content,
|
|
715
|
+
meta: { roomName }
|
|
716
|
+
});
|
|
717
|
+
if (typeof destination.channel === "function") {
|
|
718
|
+
roomName = buildDomainEventChannelName(destination.channel, ctx.content.data.id);
|
|
719
|
+
emitter.in(roomName).emit(fullEventName, {
|
|
720
|
+
...ctx.content,
|
|
721
|
+
meta: {
|
|
722
|
+
roomName,
|
|
723
|
+
roomId: ctx.content.data.id
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
//#endregion
|
|
731
|
+
//#region src/utils/has-property.ts
|
|
732
|
+
function hasOwnProperty(obj, prop) {
|
|
733
|
+
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
734
|
+
}
|
|
735
|
+
//#endregion
|
|
736
|
+
export { AsymmetricKey, BaseKey, CryptoAsymmetricAlgorithm, DomainEventPublisher, DomainEventRedisPublisher, DomainEventSocketPublisher, Logger, MemoryCache, RedisCache, RedisClient, RedisJsonAdapter, RedisWatcher, SymmetricAlgorithm, SymmetricKey, VaultClient, buildCacheKey, buildRedisKeyPath, compare, createAsymmetricKeyPair, createLogger, createNoopLogger, createRedisClient, createSymmetricKey, createVaultClient, decodePemToPKCS8, decodePemToSpki, encodePKCS8ToPEM, encodeSPKIToPem, escapeRedisKey, extractTokenHeader, extractTokenPayload, getKeyUsagesForAsymmetricAlgorithm, getKeyUsagesForSymmetricAlgorithm, hasOwnProperty, hash, isAsymmetricAlgorithm, isLoggerUsable, isRedisClient, isSymmetricAlgorithm, isVaultClientUsable, normalizeAsymmetricKeyImportOptions, normalizeAsymmetricKeyPairCreateOptions, parseRedisKeyPath, setLogger, setLoggerFactory, setVaultFactory, signToken, useLogger, useVaultClient, verifyToken };
|
|
737
|
+
|
|
738
|
+
//# sourceMappingURL=index.mjs.map
|