@authup/server-kit 1.0.0-beta.23 → 1.0.0-beta.25

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.
Files changed (101) hide show
  1. package/LICENSE +1 -1
  2. package/dist/crypto/index.d.ts +3 -1
  3. package/dist/crypto/index.d.ts.map +1 -1
  4. package/dist/crypto/json-web-token/extract.d.ts +7 -2
  5. package/dist/crypto/json-web-token/extract.d.ts.map +1 -1
  6. package/dist/crypto/json-web-token/sign/module.d.ts +1 -1
  7. package/dist/crypto/json-web-token/sign/module.d.ts.map +1 -1
  8. package/dist/crypto/json-web-token/sign/types.d.ts +10 -5
  9. package/dist/crypto/json-web-token/sign/types.d.ts.map +1 -1
  10. package/dist/crypto/json-web-token/type.d.ts +1 -1
  11. package/dist/crypto/json-web-token/type.d.ts.map +1 -1
  12. package/dist/crypto/json-web-token/utils.d.ts +2 -2
  13. package/dist/crypto/json-web-token/utils.d.ts.map +1 -1
  14. package/dist/crypto/json-web-token/verify/module.d.ts +2 -2
  15. package/dist/crypto/json-web-token/verify/module.d.ts.map +1 -1
  16. package/dist/crypto/json-web-token/verify/types.d.ts +10 -5
  17. package/dist/crypto/json-web-token/verify/types.d.ts.map +1 -1
  18. package/dist/crypto/key/container.d.ts +14 -0
  19. package/dist/crypto/key/container.d.ts.map +1 -0
  20. package/dist/crypto/key/index.d.ts +3 -0
  21. package/dist/crypto/key/index.d.ts.map +1 -0
  22. package/dist/crypto/key/key-usages.d.ts +2 -0
  23. package/dist/crypto/key/key-usages.d.ts.map +1 -0
  24. package/dist/crypto/key/types.d.ts +14 -0
  25. package/dist/crypto/key/types.d.ts.map +1 -0
  26. package/dist/crypto/key-asymmetric/check.d.ts +3 -0
  27. package/dist/crypto/key-asymmetric/check.d.ts.map +1 -0
  28. package/dist/crypto/key-asymmetric/constants.d.ts +8 -0
  29. package/dist/crypto/key-asymmetric/constants.d.ts.map +1 -0
  30. package/dist/crypto/key-asymmetric/create.d.ts +3 -0
  31. package/dist/crypto/key-asymmetric/create.d.ts.map +1 -0
  32. package/dist/crypto/key-asymmetric/helpers/index.d.ts +2 -0
  33. package/dist/crypto/key-asymmetric/helpers/index.d.ts.map +1 -0
  34. package/dist/crypto/key-asymmetric/helpers/wrap.d.ts +5 -0
  35. package/dist/crypto/key-asymmetric/helpers/wrap.d.ts.map +1 -0
  36. package/dist/crypto/key-asymmetric/index.d.ts +8 -0
  37. package/dist/crypto/key-asymmetric/index.d.ts.map +1 -0
  38. package/dist/crypto/key-asymmetric/key-usages.d.ts +5 -0
  39. package/dist/crypto/key-asymmetric/key-usages.d.ts.map +1 -0
  40. package/dist/crypto/key-asymmetric/normalize.d.ts +4 -0
  41. package/dist/crypto/key-asymmetric/normalize.d.ts.map +1 -0
  42. package/dist/crypto/key-asymmetric/types.d.ts +30 -0
  43. package/dist/crypto/key-asymmetric/types.d.ts.map +1 -0
  44. package/dist/crypto/key-symmetric/check.d.ts +3 -0
  45. package/dist/crypto/key-symmetric/check.d.ts.map +1 -0
  46. package/dist/crypto/key-symmetric/constants.d.ts +7 -0
  47. package/dist/crypto/key-symmetric/constants.d.ts.map +1 -0
  48. package/dist/crypto/key-symmetric/create.d.ts +3 -0
  49. package/dist/crypto/key-symmetric/create.d.ts.map +1 -0
  50. package/dist/crypto/key-symmetric/index.d.ts +6 -0
  51. package/dist/crypto/key-symmetric/index.d.ts.map +1 -0
  52. package/dist/crypto/key-symmetric/key-usages.d.ts +2 -0
  53. package/dist/crypto/key-symmetric/key-usages.d.ts.map +1 -0
  54. package/dist/crypto/key-symmetric/normalize.d.ts +4 -0
  55. package/dist/crypto/key-symmetric/normalize.d.ts.map +1 -0
  56. package/dist/crypto/key-symmetric/types.d.ts +27 -0
  57. package/dist/crypto/key-symmetric/types.d.ts.map +1 -0
  58. package/dist/domain-event/module.d.ts +1 -1
  59. package/dist/domain-event/module.d.ts.map +1 -1
  60. package/dist/domain-event/type.d.ts +1 -1
  61. package/dist/domain-event/type.d.ts.map +1 -1
  62. package/dist/index.cjs +335 -296
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.mjs +304 -247
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/services/cache/adapters/memory.d.ts +1 -0
  67. package/dist/services/cache/adapters/memory.d.ts.map +1 -1
  68. package/dist/services/cache/adapters/redis.d.ts +1 -0
  69. package/dist/services/cache/adapters/redis.d.ts.map +1 -1
  70. package/dist/services/cache/adapters/types.d.ts +1 -0
  71. package/dist/services/cache/adapters/types.d.ts.map +1 -1
  72. package/dist/services/logger/module.d.ts.map +1 -1
  73. package/package.json +15 -8
  74. package/dist/crypto/key-pair/constants.d.ts +0 -5
  75. package/dist/crypto/key-pair/constants.d.ts.map +0 -1
  76. package/dist/crypto/key-pair/create.d.ts +0 -3
  77. package/dist/crypto/key-pair/create.d.ts.map +0 -1
  78. package/dist/crypto/key-pair/delete.d.ts +0 -3
  79. package/dist/crypto/key-pair/delete.d.ts.map +0 -1
  80. package/dist/crypto/key-pair/helpers/check.d.ts +0 -4
  81. package/dist/crypto/key-pair/helpers/check.d.ts.map +0 -1
  82. package/dist/crypto/key-pair/helpers/file-name.d.ts +0 -4
  83. package/dist/crypto/key-pair/helpers/file-name.d.ts.map +0 -1
  84. package/dist/crypto/key-pair/helpers/index.d.ts +0 -6
  85. package/dist/crypto/key-pair/helpers/index.d.ts.map +0 -1
  86. package/dist/crypto/key-pair/helpers/options.d.ts +0 -3
  87. package/dist/crypto/key-pair/helpers/options.d.ts.map +0 -1
  88. package/dist/crypto/key-pair/helpers/private-key.d.ts +0 -3
  89. package/dist/crypto/key-pair/helpers/private-key.d.ts.map +0 -1
  90. package/dist/crypto/key-pair/helpers/wrap.d.ts +0 -5
  91. package/dist/crypto/key-pair/helpers/wrap.d.ts.map +0 -1
  92. package/dist/crypto/key-pair/index.d.ts +0 -9
  93. package/dist/crypto/key-pair/index.d.ts.map +0 -1
  94. package/dist/crypto/key-pair/load.d.ts +0 -3
  95. package/dist/crypto/key-pair/load.d.ts.map +0 -1
  96. package/dist/crypto/key-pair/module.d.ts +0 -3
  97. package/dist/crypto/key-pair/module.d.ts.map +0 -1
  98. package/dist/crypto/key-pair/save.d.ts +0 -3
  99. package/dist/crypto/key-pair/save.d.ts.map +0 -1
  100. package/dist/crypto/key-pair/type.d.ts +0 -64
  101. package/dist/crypto/key-pair/type.d.ts.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,39 +1,21 @@
1
1
  'use strict';
2
2
 
3
3
  var bcrypt = require('@node-rs/bcrypt');
4
- var node_crypto = require('node:crypto');
4
+ var uncrypto = require('uncrypto');
5
5
  var kit = require('@authup/kit');
6
- var path = require('node:path');
7
- var fs = require('node:fs');
6
+ var specs = require('@authup/specs');
8
7
  var jsonwebtoken = require('@node-rs/jsonwebtoken');
9
8
  var smob = require('smob');
10
9
  var redisExtension = require('redis-extension');
11
10
  var singa = require('singa');
12
11
  var TTLCache = require('@isaacs/ttlcache');
13
- var process$1 = require('node:process');
12
+ var path = require('node:path');
13
+ var process = require('node:process');
14
14
  var winston = require('winston');
15
15
  var vault = require('@hapic/vault');
16
+ var coreRealtimeKit = require('@authup/core-realtime-kit');
16
17
  var redisEmitter = require('@socket.io/redis-emitter');
17
18
 
18
- function _interopNamespaceDefault(e) {
19
- var n = Object.create(null);
20
- if (e) {
21
- Object.keys(e).forEach(function (k) {
22
- if (k !== 'default') {
23
- var d = Object.getOwnPropertyDescriptor(e, k);
24
- Object.defineProperty(n, k, d.get ? d : {
25
- enumerable: true,
26
- get: function () { return e[k]; }
27
- });
28
- }
29
- });
30
- }
31
- n.default = e;
32
- return Object.freeze(n);
33
- }
34
-
35
- var process__namespace = /*#__PURE__*/_interopNamespaceDefault(process$1);
36
-
37
19
  async function compare(value, hashedValue) {
38
20
  return bcrypt.compare(value, hashedValue);
39
21
  }
@@ -47,103 +29,124 @@ async function hash(str, rounds = 10) {
47
29
  * Author Peter Placzek (tada5hi)
48
30
  * For the full copyright and license information,
49
31
  * view the LICENSE file that was distributed with this source code.
50
- */ var KeyPairKind = /*#__PURE__*/ function(KeyPairKind) {
51
- KeyPairKind["PRIVATE"] = "private";
52
- KeyPairKind["PUBLIC"] = "public";
53
- return KeyPairKind;
32
+ */ var CryptoAsymmetricAlgorithm = /*#__PURE__*/ function(CryptoAsymmetricAlgorithm) {
33
+ CryptoAsymmetricAlgorithm["RSA_PSS"] = "RSA-PSS";
34
+ CryptoAsymmetricAlgorithm["RSASSA_PKCS1_V1_5"] = "RSASSA-PKCS1-v1_5";
35
+ CryptoAsymmetricAlgorithm["RSA_OAEP"] = "RSA-OAEP";
36
+ CryptoAsymmetricAlgorithm["ECDSA"] = "ECDSA";
37
+ CryptoAsymmetricAlgorithm["ECDH"] = "ECDH";
38
+ return CryptoAsymmetricAlgorithm;
54
39
  }({});
55
40
 
56
- function isKeyPair(data) {
57
- return kit.isObject(data) && typeof data.privateKey !== 'undefined' && typeof data.publicKey !== 'undefined';
58
- }
59
- function isKeyPairWithPublicKey(data) {
60
- return kit.isObject(data) && typeof data.publicKey !== 'undefined';
41
+ function isAsymmetricAlgorithm(input) {
42
+ return Object.values(CryptoAsymmetricAlgorithm).indexOf(input) !== -1;
61
43
  }
62
44
 
63
- function extendKeyPairOptions(options) {
64
- var _options;
65
- options = options ?? {};
66
- options.directory = options.directory || process.cwd();
67
- options.directory = path.isAbsolute(options.directory) ? options.directory : path.resolve(process.cwd(), options.directory);
68
- (_options = options).type ?? (_options.type = 'rsa');
69
- if (options.type === 'rsa' || options.type === 'rsa-pss' || options.type === 'dsa') {
70
- options.modulusLength = 2048;
71
- }
72
- if (!options.privateKeyEncoding) {
73
- options.privateKeyEncoding = {
74
- type: 'pkcs8',
75
- format: 'pem'
76
- };
45
+ /**
46
+ * @see https://nodejs.org/api/webcrypto.html#cryptokeyusages
47
+ */ function getKeyUsagesForAsymmetricAlgorithm(name, format) {
48
+ if (name === CryptoAsymmetricAlgorithm.RSA_PSS || name === CryptoAsymmetricAlgorithm.ECDSA || name === CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5) {
49
+ if (format === 'spki') {
50
+ return [
51
+ 'verify'
52
+ ];
53
+ }
54
+ if (format === 'pkcs8') {
55
+ return [
56
+ 'sign'
57
+ ];
58
+ }
59
+ return [
60
+ 'sign',
61
+ 'verify'
62
+ ];
77
63
  }
78
- if (!options.publicKeyEncoding) {
79
- options.publicKeyEncoding = {
80
- type: 'spki',
81
- format: 'pem'
82
- };
64
+ if (name === CryptoAsymmetricAlgorithm.ECDH) {
65
+ if (format === 'spki') {
66
+ return [];
67
+ }
68
+ return [
69
+ 'deriveKey',
70
+ 'deriveBits'
71
+ ];
83
72
  }
84
- if (options.privateKeyEncoding.passphrase && !options.privateKeyEncoding.cipher) {
85
- options.privateKeyEncoding.cipher = 'aes-256-cbc';
73
+ if (name === CryptoAsymmetricAlgorithm.RSA_OAEP) {
74
+ if (format === 'spki') {
75
+ return [
76
+ 'encrypt'
77
+ ];
78
+ }
79
+ if (format === 'pkcs8') {
80
+ return [
81
+ 'decrypt'
82
+ ];
83
+ }
84
+ return [
85
+ 'encrypt',
86
+ 'decrypt'
87
+ ];
86
88
  }
87
- return options;
89
+ throw new SyntaxError(`Key usages can not be determined for asymmetric algorithm: ${name}`);
88
90
  }
89
91
 
90
- function buildKeyFileName(type, context) {
91
- const options = extendKeyPairOptions(context);
92
- const parts = [];
93
- switch(type){
94
- case KeyPairKind.PRIVATE:
92
+ function normalizeAsymmetricKeyPairCreateOptions(options) {
93
+ let optionsNormalized;
94
+ switch(options.name){
95
+ case CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5:
96
+ case CryptoAsymmetricAlgorithm.RSA_PSS:
97
+ case CryptoAsymmetricAlgorithm.RSA_OAEP:
95
98
  {
96
- if (options.privateName) {
97
- parts.push(options.privateName);
98
- } else {
99
- parts.push(type);
100
- }
101
- if (options.privateExtension) {
102
- if (options.privateExtension.startsWith('.')) {
103
- options.privateExtension = options.privateExtension.slice(1);
104
- }
105
- parts.push(options.privateExtension);
106
- } else {
107
- parts.push('pem');
108
- }
99
+ optionsNormalized = {
100
+ modulusLength: 2048,
101
+ publicExponent: new Uint8Array([
102
+ 0x01,
103
+ 0x00,
104
+ 0x01
105
+ ]),
106
+ hash: 'SHA-256',
107
+ ...options
108
+ };
109
109
  break;
110
110
  }
111
- case KeyPairKind.PUBLIC:
111
+ case CryptoAsymmetricAlgorithm.ECDSA:
112
+ case CryptoAsymmetricAlgorithm.ECDH:
112
113
  {
113
- if (options.publicName) {
114
- parts.push(options.publicName);
115
- } else {
116
- parts.push(type);
117
- }
118
- if (options.publicExtension) {
119
- if (options.publicExtension.startsWith('.')) {
120
- options.publicExtension = options.publicExtension.slice(1);
121
- }
122
- parts.push(options.publicExtension);
123
- } else {
124
- parts.push('pem');
125
- }
114
+ optionsNormalized = {
115
+ namedCurve: 'P-256',
116
+ ...options
117
+ };
118
+ }
119
+ }
120
+ return optionsNormalized;
121
+ }
122
+ function normalizeAsymmetricKeyImportOptions(options) {
123
+ let optionsNormalized;
124
+ switch(options.name){
125
+ case CryptoAsymmetricAlgorithm.RSASSA_PKCS1_V1_5:
126
+ case CryptoAsymmetricAlgorithm.RSA_PSS:
127
+ case CryptoAsymmetricAlgorithm.RSA_OAEP:
128
+ {
129
+ optionsNormalized = {
130
+ hash: 'SHA-256',
131
+ ...options
132
+ };
126
133
  break;
127
134
  }
135
+ case CryptoAsymmetricAlgorithm.ECDSA:
136
+ case CryptoAsymmetricAlgorithm.ECDH:
137
+ {
138
+ optionsNormalized = {
139
+ namedCurve: 'P-256',
140
+ ...options
141
+ };
142
+ }
128
143
  }
129
- return parts.join('.');
144
+ return optionsNormalized;
130
145
  }
131
146
 
132
- function decryptRSAPrivateKey(context, key) {
133
- const privateKey = node_crypto.createPrivateKey({
134
- type: context.privateKeyEncoding.type,
135
- format: context.privateKeyEncoding.format,
136
- key,
137
- passphrase: context.privateKeyEncoding.passphrase || context.passphrase
138
- });
139
- let content = privateKey.export({
140
- type: context.privateKeyEncoding.type,
141
- format: context.privateKeyEncoding.format
142
- });
143
- if (typeof content !== 'string') {
144
- content = Buffer.from(content).toString('utf-8');
145
- }
146
- return content;
147
+ async function createAsymmetricKeyPair(options) {
148
+ const optionsNormalized = normalizeAsymmetricKeyPairCreateOptions(options);
149
+ return uncrypto.subtle.generateKey(optionsNormalized, true, getKeyUsagesForAsymmetricAlgorithm(optionsNormalized.name));
147
150
  }
148
151
 
149
152
  /*
@@ -151,172 +154,169 @@ function decryptRSAPrivateKey(context, key) {
151
154
  * Author Peter Placzek (tada5hi)
152
155
  * For the full copyright and license information,
153
156
  * view the LICENSE file that was distributed with this source code.
154
- */ function wrapPem(type, input) {
155
- if (typeof input !== 'string') {
156
- input = Buffer.from(input).toString('base64');
157
- }
157
+ */ function enc(type, input) {
158
158
  return `-----BEGIN ${type}-----\n${input}\n-----END ${type}-----`;
159
159
  }
160
- function wrapPrivateKeyPem(input) {
161
- return wrapPem('PRIVATE KEY', input);
160
+ function encodePKCS8ToPEM(base64) {
161
+ return enc('PRIVATE KEY', base64);
162
162
  }
163
- function wrapPublicKeyPem(input) {
164
- return wrapPem('PUBLIC KEY', input);
163
+ function encodeSPKIToPem(input) {
164
+ return enc('PUBLIC KEY', input);
165
165
  }
166
166
  // ------------------------------------------------------------
167
- function unwrapPem(type, input) {
168
- if (typeof input !== 'string') {
169
- input = Buffer.from(input).toString('base64');
170
- }
167
+ function dec(type, input) {
171
168
  input = input.replace(`-----BEGIN ${type}-----\n`, '');
172
169
  input = input.replace(`\n-----END ${type}-----\n`, '');
173
170
  input = input.replace(`-----END ${type}-----\n`, '');
174
171
  input = input.replace(`\n-----END ${type}-----`, '');
175
172
  return input;
176
173
  }
177
- function unwrapPrivateKeyPem(input) {
178
- return unwrapPem('PRIVATE KEY', input);
174
+ function decodePemToPKCS8(input) {
175
+ return dec('PRIVATE KEY', input);
179
176
  }
180
- function unwrapPublicKeyPem(input) {
181
- return unwrapPem('PUBLIC KEY', input);
177
+ function decodePemToSpki(input) {
178
+ return dec('PUBLIC KEY', input);
182
179
  }
183
180
 
184
- async function saveKeyPair(keyPair, context) {
185
- context = extendKeyPairOptions(context);
186
- await fs.promises.mkdir(context.directory, {
187
- recursive: true
188
- });
189
- await Promise.all([
190
- {
191
- path: path.resolve(context.directory, buildKeyFileName(KeyPairKind.PRIVATE, context)),
192
- content: keyPair.privateKey
193
- },
194
- {
195
- path: path.resolve(context.directory, buildKeyFileName(KeyPairKind.PUBLIC, context)),
196
- content: keyPair.publicKey
197
- }
198
- ].map((file)=>fs.promises.writeFile(file.path, file.content)));
199
- return keyPair;
200
- }
201
-
202
- async function createKeyPair(context) {
203
- const options = extendKeyPairOptions(context);
204
- const keyPair = await new Promise((resolve, reject)=>{
205
- const callback = (err, publicKey, privateKey)=>{
206
- if (err) reject(err);
207
- resolve({
208
- privateKey,
209
- publicKey
210
- });
181
+ /*
182
+ * Copyright (c) 2024.
183
+ * Author Peter Placzek (tada5hi)
184
+ * For the full copyright and license information,
185
+ * view the LICENSE file that was distributed with this source code.
186
+ */ var SymmetricAlgorithm = /*#__PURE__*/ function(SymmetricAlgorithm) {
187
+ SymmetricAlgorithm["HMAC"] = "HMAC";
188
+ SymmetricAlgorithm["AES_CTR"] = "AES-CTR";
189
+ SymmetricAlgorithm["AES_CBC"] = "AES-CBC";
190
+ SymmetricAlgorithm["AES_GCM"] = "AES-GCM";
191
+ return SymmetricAlgorithm;
192
+ }({});
193
+
194
+ function normalizeSymmetricKeyCreateOptions(input) {
195
+ if (input.name === SymmetricAlgorithm.HMAC) {
196
+ return {
197
+ hash: 'SHA-256',
198
+ ...input
211
199
  };
212
- switch(options.type){
213
- case 'dsa':
214
- node_crypto.generateKeyPair(options.type, options, callback);
215
- break;
216
- case 'ec':
217
- node_crypto.generateKeyPair(options.type, options, callback);
218
- break;
219
- case 'rsa':
220
- node_crypto.generateKeyPair(options.type, options, callback);
221
- break;
222
- case 'rsa-pss':
223
- node_crypto.generateKeyPair(options.type, options, callback);
224
- break;
225
- }
226
- });
227
- if (options.save) {
228
- await saveKeyPair(keyPair, options);
229
200
  }
230
- if (options.passphrase || options.privateKeyEncoding.passphrase) {
231
- keyPair.privateKey = decryptRSAPrivateKey(options, keyPair.privateKey);
201
+ return {
202
+ length: 256,
203
+ name: input.name
204
+ };
205
+ }
206
+ function normalizeSymmetricKeyImportOptions(input) {
207
+ if (input.name === SymmetricAlgorithm.HMAC) {
208
+ return {
209
+ hash: 'SHA-256',
210
+ ...input
211
+ };
232
212
  }
233
- return keyPair;
213
+ return input;
234
214
  }
235
215
 
236
- async function deleteKeyPair(context) {
237
- const options = extendKeyPairOptions(context);
238
- const privateKeyPath = path.resolve(options.directory, buildKeyFileName(KeyPairKind.PRIVATE, options));
239
- const publicKeyPath = path.resolve(options.directory, buildKeyFileName(KeyPairKind.PUBLIC, options));
240
- try {
241
- await Promise.all([
242
- privateKeyPath,
243
- publicKeyPath
244
- ].map((filePath)=>fs.promises.stat(filePath)));
245
- } catch (e) {
246
- return;
216
+ function isSymmetricAlgorithm(input) {
217
+ return Object.values(SymmetricAlgorithm).indexOf(input) !== -1;
218
+ }
219
+
220
+ function getKeyUsagesForSymmetricAlgorithm(name) {
221
+ /**
222
+ * @see https://nodejs.org/api/webcrypto.html#cryptokeyusages
223
+ */ if (name === SymmetricAlgorithm.HMAC) {
224
+ return [
225
+ 'sign',
226
+ 'verify'
227
+ ];
228
+ }
229
+ if (name === SymmetricAlgorithm.AES_CBC || name === SymmetricAlgorithm.AES_GCM || name === SymmetricAlgorithm.AES_CTR) {
230
+ return [
231
+ 'encrypt',
232
+ 'decrypt'
233
+ ];
247
234
  }
248
- await Promise.all([
249
- privateKeyPath,
250
- publicKeyPath
251
- ].map((filePath)=>fs.promises.rm(filePath)));
235
+ throw new SyntaxError(`Key usages can not be determined for symmetric algorithm: ${name}`);
252
236
  }
253
237
 
254
- async function loadKeyPair(context) {
255
- const options = extendKeyPairOptions(context);
256
- const privateKeyPath = path.resolve(options.directory, buildKeyFileName(KeyPairKind.PRIVATE, options));
257
- try {
258
- await fs.promises.stat(privateKeyPath);
259
- } catch (e) {
260
- return undefined;
238
+ async function createSymmetricKey(input) {
239
+ const optionsNormalized = normalizeSymmetricKeyCreateOptions(input);
240
+ return uncrypto.subtle.generateKey(optionsNormalized, true, getKeyUsagesForSymmetricAlgorithm(optionsNormalized.name));
241
+ }
242
+
243
+ function getKeyUsagesForAlgorithm(name, format) {
244
+ if (isAsymmetricAlgorithm(name)) {
245
+ return getKeyUsagesForAsymmetricAlgorithm(name, format);
261
246
  }
262
- const privateKeyBuffer = await fs.promises.readFile(privateKeyPath);
263
- let privateKey = privateKeyBuffer.toString();
264
- if (options.passphrase || options.privateKeyEncoding.passphrase) {
265
- privateKey = decryptRSAPrivateKey(options, privateKey);
247
+ if (isSymmetricAlgorithm(name)) {
248
+ return getKeyUsagesForSymmetricAlgorithm(name);
266
249
  }
267
- const publicKeyPath = path.resolve(options.directory, buildKeyFileName(KeyPairKind.PUBLIC, options));
268
- let publicKey;
269
- try {
270
- await fs.promises.stat(publicKeyPath);
271
- const publicKeyBuffer = await fs.promises.readFile(publicKeyPath);
272
- publicKey = publicKeyBuffer.toString();
273
- } catch (e) {
274
- const publicKeyObject = node_crypto.createPublicKey({
275
- key: privateKey,
276
- format: options.privateKeyEncoding.format,
277
- type: options.publicKeyEncoding.type
278
- });
279
- const stringOrBuffer = publicKeyObject.export({
280
- format: options.publicKeyEncoding.format,
281
- type: options.publicKeyEncoding.type
282
- });
283
- if (typeof stringOrBuffer !== 'string') {
284
- publicKey = stringOrBuffer.toString();
285
- } else {
286
- publicKey = stringOrBuffer;
250
+ throw new SyntaxError(`Key usages can not be determined for algorithm: ${name}`);
251
+ }
252
+
253
+ class CryptoKeyContainer {
254
+ // ----------------------------------------------
255
+ async toArrayBuffer() {
256
+ if (this.key.type === 'private') {
257
+ return uncrypto.subtle.exportKey('pkcs8', this.key);
287
258
  }
288
- if (options.save) {
289
- await saveKeyPair({
290
- privateKey,
291
- publicKey
292
- }, options);
259
+ if (this.key.type === 'public') {
260
+ return uncrypto.subtle.exportKey('spki', this.key);
293
261
  }
262
+ return uncrypto.subtle.exportKey('raw', this.key);
294
263
  }
295
- return {
296
- privateKey,
297
- publicKey
298
- };
299
- }
300
-
301
- const keyPairCache = {};
302
- async function useKeyPair(value) {
303
- let options;
304
- if (typeof value === 'string') {
305
- options = extendKeyPairOptions({
306
- privateName: value
264
+ async toUint8Array() {
265
+ const arrayBuffer = await this.toArrayBuffer();
266
+ return new Uint8Array(arrayBuffer);
267
+ }
268
+ async toBase64() {
269
+ const arrayBuffer = await this.toArrayBuffer();
270
+ return kit.arrayBufferToBase64(arrayBuffer);
271
+ }
272
+ async toPem() {
273
+ const base64 = await this.toBase64();
274
+ if (this.key.type === 'public') {
275
+ return encodeSPKIToPem(base64);
276
+ }
277
+ if (this.key.type === 'private') {
278
+ return encodePKCS8ToPEM(base64);
279
+ }
280
+ throw new Error('A symmetric key can not be encoded as PEM');
281
+ }
282
+ async toJWK() {
283
+ return uncrypto.subtle.exportKey('jwk', this.key);
284
+ }
285
+ // ----------------------------------------------
286
+ static async fromPem(ctx) {
287
+ if (ctx.format === 'pkcs8') {
288
+ return CryptoKeyContainer.fromBase64({
289
+ ...ctx,
290
+ key: decodePemToPKCS8(ctx.key)
291
+ });
292
+ }
293
+ return CryptoKeyContainer.fromBase64({
294
+ ...ctx,
295
+ key: decodePemToSpki(ctx.key)
307
296
  });
308
- } else {
309
- options = extendKeyPairOptions(value || {});
310
297
  }
311
- if (Object.prototype.hasOwnProperty.call(keyPairCache, options.privateName)) {
312
- return keyPairCache[options.privateName];
298
+ static async fromBase64(ctx) {
299
+ const arrayBuffer = kit.base64ToArrayBuffer(ctx.key);
300
+ return CryptoKeyContainer.fromArrayBuffer({
301
+ ...ctx,
302
+ key: arrayBuffer
303
+ });
304
+ }
305
+ static async fromArrayBuffer(ctx) {
306
+ let normalizedOptions;
307
+ if (ctx.format === 'spki' || ctx.format === 'pkcs8') {
308
+ normalizedOptions = normalizeAsymmetricKeyImportOptions(ctx.options);
309
+ } else if (ctx.format === 'raw') {
310
+ normalizedOptions = normalizeSymmetricKeyImportOptions(ctx.options);
311
+ } else {
312
+ throw new SyntaxError(`Format ${ctx.format} is not supported.`);
313
+ }
314
+ const cryptoKey = await uncrypto.subtle.importKey(ctx.format, ctx.key, normalizedOptions, true, getKeyUsagesForAlgorithm(normalizedOptions.name, ctx.format));
315
+ return new CryptoKeyContainer(cryptoKey);
313
316
  }
314
- let keyPair = await loadKeyPair(options);
315
- if (typeof keyPair === 'undefined') {
316
- keyPair = await createKeyPair(options);
317
+ constructor(cryptoKey){
318
+ this.key = cryptoKey;
317
319
  }
318
- keyPairCache[options.privateName] = keyPair;
319
- return keyPair;
320
320
  }
321
321
 
322
322
  /**
@@ -324,11 +324,11 @@ async function useKeyPair(value) {
324
324
  *
325
325
  * @param token
326
326
  *
327
- * @throws TokenError
327
+ * @throws JWTError
328
328
  */ function extractTokenHeader(token) {
329
329
  const parts = token.split('.');
330
330
  if (parts.length !== 3) {
331
- throw kit.TokenError.payloadInvalid('The token format is not valid.');
331
+ throw specs.JWTError.invalid();
332
332
  }
333
333
  const [headerBase64] = parts;
334
334
  try {
@@ -347,20 +347,24 @@ async function useKeyPair(value) {
347
347
  'x5t#S256': header.x5TS256CertThumbprint,
348
348
  };
349
349
  */ } catch (e) {
350
- throw kit.TokenError.headerInvalid('The token header could not be extracted.');
350
+ throw specs.JWTError.headerInvalid('The token header could not be extracted.');
351
351
  }
352
352
  }
353
- function extractTokenPayload(token) {
353
+ /**
354
+ * @param token
355
+ *
356
+ * @throws JWTError
357
+ */ function extractTokenPayload(token) {
354
358
  const parts = token.split('.');
355
359
  if (parts.length !== 3) {
356
- throw kit.TokenError.payloadInvalid('The token format is not valid.');
360
+ throw specs.JWTError.invalid();
357
361
  }
358
362
  const [, payloadBase64] = parts;
359
363
  try {
360
364
  const payload = atob(payloadBase64);
361
365
  return JSON.parse(payload);
362
366
  } catch (e) {
363
- throw kit.TokenError.payloadInvalid('The token payload could not be extracted.');
367
+ throw specs.JWTError.payloadInvalid('The token payload could not be extracted.');
364
368
  }
365
369
  }
366
370
 
@@ -370,19 +374,19 @@ function createErrorForJWTError(e) {
370
374
  switch(e.name){
371
375
  case 'TokenExpiredError':
372
376
  {
373
- return kit.TokenError.expired();
377
+ return specs.JWTError.expired();
374
378
  }
375
379
  case 'NotBeforeError':
376
380
  {
377
381
  if (typeof e.date === 'string' || e.date instanceof Date) {
378
- return kit.TokenError.notActiveBefore(e.date);
382
+ return specs.JWTError.notActiveBefore(e.date);
379
383
  }
380
384
  break;
381
385
  }
382
386
  case 'JsonWebTokenError':
383
387
  {
384
388
  if (typeof e.message === 'string') {
385
- return kit.TokenError.payloadInvalid(e.message);
389
+ return specs.JWTError.payloadInvalid(e.message);
386
390
  }
387
391
  break;
388
392
  }
@@ -392,20 +396,20 @@ function createErrorForJWTError(e) {
392
396
  switch(e.message){
393
397
  case 'ExpiredSignature':
394
398
  {
395
- return kit.TokenError.expired();
399
+ return specs.JWTError.expired();
396
400
  }
397
401
  case 'ImmatureSignature':
398
402
  {
399
- return kit.TokenError.notActiveBefore();
403
+ return specs.JWTError.notActiveBefore();
400
404
  }
401
405
  case 'InvalidToken':
402
406
  case 'InvalidSignature':
403
407
  {
404
- return kit.TokenError.payloadInvalid();
408
+ return specs.JWTError.payloadInvalid();
405
409
  }
406
410
  }
407
411
  }
408
- return new kit.TokenError({
412
+ return new specs.JWTError({
409
413
  cause: e,
410
414
  logMessage: true,
411
415
  message: 'The JWT error could not be determined.'
@@ -413,47 +417,47 @@ function createErrorForJWTError(e) {
413
417
  }
414
418
  function transformJWTAlgorithmToInternal(algorithm) {
415
419
  switch(algorithm){
416
- case kit.JWTAlgorithm.HS256:
420
+ case specs.JWTAlgorithm.HS256:
417
421
  {
418
422
  return jsonwebtoken.Algorithm.HS256;
419
423
  }
420
- case kit.JWTAlgorithm.HS384:
424
+ case specs.JWTAlgorithm.HS384:
421
425
  {
422
426
  return jsonwebtoken.Algorithm.HS384;
423
427
  }
424
- case kit.JWTAlgorithm.HS512:
428
+ case specs.JWTAlgorithm.HS512:
425
429
  {
426
430
  return jsonwebtoken.Algorithm.HS512;
427
431
  }
428
- case kit.JWTAlgorithm.RS256:
432
+ case specs.JWTAlgorithm.RS256:
429
433
  {
430
434
  return jsonwebtoken.Algorithm.RS256;
431
435
  }
432
- case kit.JWTAlgorithm.RS384:
436
+ case specs.JWTAlgorithm.RS384:
433
437
  {
434
438
  return jsonwebtoken.Algorithm.RS384;
435
439
  }
436
- case kit.JWTAlgorithm.RS512:
440
+ case specs.JWTAlgorithm.RS512:
437
441
  {
438
442
  return jsonwebtoken.Algorithm.RS512;
439
443
  }
440
- case kit.JWTAlgorithm.ES256:
444
+ case specs.JWTAlgorithm.ES256:
441
445
  {
442
446
  return jsonwebtoken.Algorithm.ES256;
443
447
  }
444
- case kit.JWTAlgorithm.ES384:
448
+ case specs.JWTAlgorithm.ES384:
445
449
  {
446
450
  return jsonwebtoken.Algorithm.ES384;
447
451
  }
448
- case kit.JWTAlgorithm.PS256:
452
+ case specs.JWTAlgorithm.PS256:
449
453
  {
450
454
  return jsonwebtoken.Algorithm.PS256;
451
455
  }
452
- case kit.JWTAlgorithm.PS384:
456
+ case specs.JWTAlgorithm.PS384:
453
457
  {
454
458
  return jsonwebtoken.Algorithm.PS384;
455
459
  }
456
- case kit.JWTAlgorithm.PS512:
460
+ case specs.JWTAlgorithm.PS512:
457
461
  {
458
462
  return jsonwebtoken.Algorithm.PS512;
459
463
  }
@@ -470,31 +474,44 @@ async function signToken(claims, context) {
470
474
  claims.iat = getUtcTimestamp();
471
475
  }
472
476
  switch(context.type){
473
- case kit.JWKType.RSA:
474
- case kit.JWKType.EC:
477
+ case specs.JWKType.RSA:
478
+ case specs.JWKType.EC:
475
479
  {
476
- const { privateKey } = isKeyPair(context.keyPair) ? context.keyPair : await useKeyPair(context.keyPair);
477
480
  let algorithm;
478
- if (context.type === kit.JWKType.RSA) {
481
+ let key;
482
+ if (typeof context.key === 'string') {
483
+ key = encodePKCS8ToPEM(context.key);
484
+ } else {
485
+ const keyContainer = new CryptoKeyContainer(context.key);
486
+ key = await keyContainer.toPem();
487
+ }
488
+ if (context.type === specs.JWKType.RSA) {
479
489
  algorithm = context.algorithm ? transformJWTAlgorithmToInternal(context.algorithm) : jsonwebtoken.Algorithm.RS256;
480
490
  } else {
481
491
  algorithm = context.algorithm ? transformJWTAlgorithmToInternal(context.algorithm) : jsonwebtoken.Algorithm.ES256;
482
492
  }
483
- return jsonwebtoken.sign(claims, privateKey, {
493
+ return jsonwebtoken.sign(claims, key, {
484
494
  algorithm,
485
495
  keyId: context.keyId
486
496
  });
487
497
  }
488
- case kit.JWKType.OCT:
498
+ case specs.JWKType.OCT:
489
499
  {
490
500
  const algorithm = context.algorithm ? transformJWTAlgorithmToInternal(context.algorithm) : jsonwebtoken.Algorithm.HS256;
491
- return jsonwebtoken.sign(claims, context.key, {
501
+ let key;
502
+ if (typeof context.key === 'string') {
503
+ key = context.key;
504
+ } else {
505
+ const keyContainer = new CryptoKeyContainer(context.key);
506
+ key = await keyContainer.toUint8Array();
507
+ }
508
+ return jsonwebtoken.sign(claims, key, {
492
509
  algorithm,
493
510
  keyId: context.keyId
494
511
  });
495
512
  }
496
513
  }
497
- throw new kit.TokenError();
514
+ throw new specs.OAuth2Error();
498
515
  }
499
516
 
500
517
  /**
@@ -503,18 +520,17 @@ async function signToken(claims, context) {
503
520
  * @param token
504
521
  * @param context
505
522
  *
506
- * @throws TokenError
523
+ * @throws OAuth2Error
507
524
  */ async function verifyToken(token, context) {
508
525
  let promise;
509
526
  let output;
510
527
  try {
511
528
  switch(context.type){
512
- case kit.JWKType.RSA:
513
- case kit.JWKType.EC:
529
+ case specs.JWKType.RSA:
530
+ case specs.JWKType.EC:
514
531
  {
515
- const { publicKey } = isKeyPairWithPublicKey(context.keyPair) ? context.keyPair : await useKeyPair(context.keyPair);
516
532
  let algorithms;
517
- if (context.type === kit.JWKType.RSA) {
533
+ if (context.type === specs.JWKType.RSA) {
518
534
  algorithms = context.algorithms ? context.algorithms.map((algorithm)=>transformJWTAlgorithmToInternal(algorithm)) : [
519
535
  jsonwebtoken.Algorithm.RS256,
520
536
  jsonwebtoken.Algorithm.RS384,
@@ -529,20 +545,34 @@ async function signToken(claims, context) {
529
545
  jsonwebtoken.Algorithm.ES384
530
546
  ];
531
547
  }
532
- promise = jsonwebtoken.verify(token, publicKey, {
548
+ let key;
549
+ if (typeof context.key === 'string') {
550
+ key = encodeSPKIToPem(context.key);
551
+ } else {
552
+ const keyContainer = new CryptoKeyContainer(context.key);
553
+ key = await keyContainer.toPem();
554
+ }
555
+ promise = jsonwebtoken.verify(token, key, {
533
556
  algorithms,
534
557
  validateNbf: true
535
558
  });
536
559
  break;
537
560
  }
538
- case kit.JWKType.OCT:
561
+ case specs.JWKType.OCT:
539
562
  {
540
563
  const algorithms = context.algorithms ? context.algorithms.map((algorithm)=>transformJWTAlgorithmToInternal(algorithm)) : [
541
564
  jsonwebtoken.Algorithm.HS256,
542
565
  jsonwebtoken.Algorithm.HS384,
543
566
  jsonwebtoken.Algorithm.HS512
544
567
  ];
545
- promise = jsonwebtoken.verify(token, context.key, {
568
+ let key;
569
+ if (typeof context.key === 'string') {
570
+ key = context.key;
571
+ } else {
572
+ const keyContainer = new CryptoKeyContainer(context.key);
573
+ key = await keyContainer.toUint8Array();
574
+ }
575
+ promise = jsonwebtoken.verify(token, key, {
546
576
  algorithms,
547
577
  validateNbf: true
548
578
  });
@@ -553,7 +583,7 @@ async function signToken(claims, context) {
553
583
  throw createErrorForJWTError(e);
554
584
  }
555
585
  if (typeof output === 'undefined') {
556
- throw new kit.TokenError({
586
+ throw new specs.OAuth2Error({
557
587
  message: 'Invalid type.'
558
588
  });
559
589
  }
@@ -577,6 +607,9 @@ function useRedisClient() {
577
607
  }
578
608
 
579
609
  class MemoryCacheAdapter {
610
+ async has(key) {
611
+ return this.instance.has(key);
612
+ }
580
613
  async get(key) {
581
614
  return this.instance.get(key);
582
615
  }
@@ -620,6 +653,10 @@ class RedisCacheAdapter {
620
653
  async get(key) {
621
654
  return this.instance.get(key);
622
655
  }
656
+ async has(key) {
657
+ const output = await this.get(key);
658
+ return typeof output !== 'undefined';
659
+ }
623
660
  async set(key, value, options) {
624
661
  await this.instance.set(key, value, {
625
662
  milliseconds: options.ttl
@@ -708,14 +745,14 @@ function useCache() {
708
745
 
709
746
  function createLogger(context) {
710
747
  let items;
711
- const cwd = context.directory || process__namespace.cwd();
748
+ const cwd = context.directory || process.cwd();
712
749
  if (context.env === 'production') {
713
750
  items = [
714
751
  new winston.transports.Console({
715
752
  level: 'info'
716
753
  }),
717
754
  new winston.transports.File({
718
- filename: path.join(cwd, 'access.log'),
755
+ filename: path.join(cwd, 'http.log'),
719
756
  level: 'http',
720
757
  maxsize: 10 * 1024 * 1024,
721
758
  maxFiles: 5
@@ -734,6 +771,7 @@ function createLogger(context) {
734
771
  })
735
772
  ];
736
773
  }
774
+ // @see https://github.com/winstonjs/triple-beam/blob/master/config/npm.js
737
775
  return winston.createLogger({
738
776
  format: winston.format.combine(winston.format.errors({
739
777
  stack: true
@@ -822,7 +860,7 @@ class DomainEventSocketPublisher {
822
860
  emitter = this.driver;
823
861
  }
824
862
  let roomName = buildDomainEventChannelName(ctx.destinations[i].channel);
825
- const fullEventName = kit.buildEventFullName(ctx.content.type, ctx.content.event);
863
+ const fullEventName = coreRealtimeKit.buildEventFullName(ctx.content.type, ctx.content.event);
826
864
  emitter.in(roomName).emit(fullEventName, {
827
865
  ...ctx.content,
828
866
  meta: {
@@ -921,46 +959,47 @@ Object.defineProperty(exports, "createVaultClient", {
921
959
  get: function () { return vault.createClient; }
922
960
  });
923
961
  exports.Cache = Cache;
962
+ exports.CryptoAsymmetricAlgorithm = CryptoAsymmetricAlgorithm;
963
+ exports.CryptoKeyContainer = CryptoKeyContainer;
924
964
  exports.DomainEventPublisher = DomainEventPublisher;
925
965
  exports.DomainEventRedisPublisher = DomainEventRedisPublisher;
926
966
  exports.DomainEventSocketPublisher = DomainEventSocketPublisher;
927
- exports.KeyPairKind = KeyPairKind;
928
967
  exports.MemoryCacheAdapter = MemoryCacheAdapter;
929
968
  exports.RedisCacheAdapter = RedisCacheAdapter;
969
+ exports.SymmetricAlgorithm = SymmetricAlgorithm;
930
970
  exports.buildCacheKey = buildCacheKey;
931
- exports.buildKeyFileName = buildKeyFileName;
932
971
  exports.compare = compare;
972
+ exports.createAsymmetricKeyPair = createAsymmetricKeyPair;
933
973
  exports.createCacheAdapter = createCacheAdapter;
934
- exports.createKeyPair = createKeyPair;
935
974
  exports.createLogger = createLogger;
936
- exports.decryptRSAPrivateKey = decryptRSAPrivateKey;
937
- exports.deleteKeyPair = deleteKeyPair;
938
- exports.extendKeyPairOptions = extendKeyPairOptions;
975
+ exports.createSymmetricKey = createSymmetricKey;
976
+ exports.decodePemToPKCS8 = decodePemToPKCS8;
977
+ exports.decodePemToSpki = decodePemToSpki;
978
+ exports.encodePKCS8ToPEM = encodePKCS8ToPEM;
979
+ exports.encodeSPKIToPem = encodeSPKIToPem;
939
980
  exports.extractTokenHeader = extractTokenHeader;
940
981
  exports.extractTokenPayload = extractTokenPayload;
982
+ exports.getKeyUsagesForAlgorithm = getKeyUsagesForAlgorithm;
983
+ exports.getKeyUsagesForAsymmetricAlgorithm = getKeyUsagesForAsymmetricAlgorithm;
984
+ exports.getKeyUsagesForSymmetricAlgorithm = getKeyUsagesForSymmetricAlgorithm;
941
985
  exports.hasOwnProperty = hasOwnProperty;
942
986
  exports.hash = hash;
943
- exports.isKeyPair = isKeyPair;
944
- exports.isKeyPairWithPublicKey = isKeyPairWithPublicKey;
987
+ exports.isAsymmetricAlgorithm = isAsymmetricAlgorithm;
945
988
  exports.isLoggerUsable = isLoggerUsable;
946
989
  exports.isRedisClientUsable = isRedisClientUsable;
990
+ exports.isSymmetricAlgorithm = isSymmetricAlgorithm;
947
991
  exports.isVaultClientUsable = isVaultClientUsable;
948
- exports.loadKeyPair = loadKeyPair;
949
- exports.saveKeyPair = saveKeyPair;
992
+ exports.normalizeAsymmetricKeyImportOptions = normalizeAsymmetricKeyImportOptions;
993
+ exports.normalizeAsymmetricKeyPairCreateOptions = normalizeAsymmetricKeyPairCreateOptions;
950
994
  exports.setLogger = setLogger;
951
995
  exports.setLoggerFactory = setLoggerFactory;
952
996
  exports.setRedisClient = setRedisClient;
953
997
  exports.setRedisFactory = setRedisFactory;
954
998
  exports.setVaultFactory = setVaultFactory;
955
999
  exports.signToken = signToken;
956
- exports.unwrapPrivateKeyPem = unwrapPrivateKeyPem;
957
- exports.unwrapPublicKeyPem = unwrapPublicKeyPem;
958
1000
  exports.useCache = useCache;
959
- exports.useKeyPair = useKeyPair;
960
1001
  exports.useLogger = useLogger;
961
1002
  exports.useRedisClient = useRedisClient;
962
1003
  exports.useVaultClient = useVaultClient;
963
1004
  exports.verifyToken = verifyToken;
964
- exports.wrapPrivateKeyPem = wrapPrivateKeyPem;
965
- exports.wrapPublicKeyPem = wrapPublicKeyPem;
966
1005
  //# sourceMappingURL=index.cjs.map