iron-session 8.0.0-beta.3 → 8.0.0-beta.5
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.cjs +40 -505
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -108
- package/dist/index.d.ts +3 -108
- package/dist/index.js +21 -506
- package/dist/index.js.map +1 -1
- package/package.json +12 -9
package/dist/index.cjs
CHANGED
|
@@ -1,481 +1,28 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
10
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
11
|
-
}) : x)(function(x) {
|
|
12
|
-
if (typeof require !== "undefined")
|
|
13
|
-
return require.apply(this, arguments);
|
|
14
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
15
|
-
});
|
|
16
|
-
var __commonJS = (cb, mod) => function __require2() {
|
|
17
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
18
|
-
};
|
|
19
|
-
var __copyProps = (to, from, except, desc) => {
|
|
20
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
-
for (let key of __getOwnPropNames(from))
|
|
22
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
24
|
-
}
|
|
25
|
-
return to;
|
|
26
|
-
};
|
|
27
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
28
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
29
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
30
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
31
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
32
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
33
|
-
mod
|
|
34
|
-
));
|
|
3
|
+
var cookie = require('cookie');
|
|
4
|
+
var ironWebcrypto = require('iron-webcrypto');
|
|
5
|
+
var crypto = require('uncrypto');
|
|
35
6
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
var obj = {};
|
|
48
|
-
var opt = options || {};
|
|
49
|
-
var dec = opt.decode || decode;
|
|
50
|
-
var index = 0;
|
|
51
|
-
while (index < str.length) {
|
|
52
|
-
var eqIdx = str.indexOf("=", index);
|
|
53
|
-
if (eqIdx === -1) {
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
var endIdx = str.indexOf(";", index);
|
|
57
|
-
if (endIdx === -1) {
|
|
58
|
-
endIdx = str.length;
|
|
59
|
-
} else if (endIdx < eqIdx) {
|
|
60
|
-
index = str.lastIndexOf(";", eqIdx - 1) + 1;
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
var key = str.slice(index, eqIdx).trim();
|
|
64
|
-
if (void 0 === obj[key]) {
|
|
65
|
-
var val = str.slice(eqIdx + 1, endIdx).trim();
|
|
66
|
-
if (val.charCodeAt(0) === 34) {
|
|
67
|
-
val = val.slice(1, -1);
|
|
68
|
-
}
|
|
69
|
-
obj[key] = tryDecode(val, dec);
|
|
70
|
-
}
|
|
71
|
-
index = endIdx + 1;
|
|
72
|
-
}
|
|
73
|
-
return obj;
|
|
74
|
-
}
|
|
75
|
-
function serialize2(name, val, options) {
|
|
76
|
-
var opt = options || {};
|
|
77
|
-
var enc = opt.encode || encode;
|
|
78
|
-
if (typeof enc !== "function") {
|
|
79
|
-
throw new TypeError("option encode is invalid");
|
|
80
|
-
}
|
|
81
|
-
if (!fieldContentRegExp.test(name)) {
|
|
82
|
-
throw new TypeError("argument name is invalid");
|
|
83
|
-
}
|
|
84
|
-
var value = enc(val);
|
|
85
|
-
if (value && !fieldContentRegExp.test(value)) {
|
|
86
|
-
throw new TypeError("argument val is invalid");
|
|
87
|
-
}
|
|
88
|
-
var str = name + "=" + value;
|
|
89
|
-
if (null != opt.maxAge) {
|
|
90
|
-
var maxAge = opt.maxAge - 0;
|
|
91
|
-
if (isNaN(maxAge) || !isFinite(maxAge)) {
|
|
92
|
-
throw new TypeError("option maxAge is invalid");
|
|
93
|
-
}
|
|
94
|
-
str += "; Max-Age=" + Math.floor(maxAge);
|
|
95
|
-
}
|
|
96
|
-
if (opt.domain) {
|
|
97
|
-
if (!fieldContentRegExp.test(opt.domain)) {
|
|
98
|
-
throw new TypeError("option domain is invalid");
|
|
99
|
-
}
|
|
100
|
-
str += "; Domain=" + opt.domain;
|
|
101
|
-
}
|
|
102
|
-
if (opt.path) {
|
|
103
|
-
if (!fieldContentRegExp.test(opt.path)) {
|
|
104
|
-
throw new TypeError("option path is invalid");
|
|
105
|
-
}
|
|
106
|
-
str += "; Path=" + opt.path;
|
|
107
|
-
}
|
|
108
|
-
if (opt.expires) {
|
|
109
|
-
var expires = opt.expires;
|
|
110
|
-
if (!isDate(expires) || isNaN(expires.valueOf())) {
|
|
111
|
-
throw new TypeError("option expires is invalid");
|
|
112
|
-
}
|
|
113
|
-
str += "; Expires=" + expires.toUTCString();
|
|
114
|
-
}
|
|
115
|
-
if (opt.httpOnly) {
|
|
116
|
-
str += "; HttpOnly";
|
|
117
|
-
}
|
|
118
|
-
if (opt.secure) {
|
|
119
|
-
str += "; Secure";
|
|
120
|
-
}
|
|
121
|
-
if (opt.partitioned) {
|
|
122
|
-
str += "; Partitioned";
|
|
123
|
-
}
|
|
124
|
-
if (opt.priority) {
|
|
125
|
-
var priority = typeof opt.priority === "string" ? opt.priority.toLowerCase() : opt.priority;
|
|
126
|
-
switch (priority) {
|
|
127
|
-
case "low":
|
|
128
|
-
str += "; Priority=Low";
|
|
129
|
-
break;
|
|
130
|
-
case "medium":
|
|
131
|
-
str += "; Priority=Medium";
|
|
132
|
-
break;
|
|
133
|
-
case "high":
|
|
134
|
-
str += "; Priority=High";
|
|
135
|
-
break;
|
|
136
|
-
default:
|
|
137
|
-
throw new TypeError("option priority is invalid");
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (opt.sameSite) {
|
|
141
|
-
var sameSite = typeof opt.sameSite === "string" ? opt.sameSite.toLowerCase() : opt.sameSite;
|
|
142
|
-
switch (sameSite) {
|
|
143
|
-
case true:
|
|
144
|
-
str += "; SameSite=Strict";
|
|
145
|
-
break;
|
|
146
|
-
case "lax":
|
|
147
|
-
str += "; SameSite=Lax";
|
|
148
|
-
break;
|
|
149
|
-
case "strict":
|
|
150
|
-
str += "; SameSite=Strict";
|
|
151
|
-
break;
|
|
152
|
-
case "none":
|
|
153
|
-
str += "; SameSite=None";
|
|
154
|
-
break;
|
|
155
|
-
default:
|
|
156
|
-
throw new TypeError("option sameSite is invalid");
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return str;
|
|
160
|
-
}
|
|
161
|
-
function decode(str) {
|
|
162
|
-
return str.indexOf("%") !== -1 ? decodeURIComponent(str) : str;
|
|
163
|
-
}
|
|
164
|
-
function encode(val) {
|
|
165
|
-
return encodeURIComponent(val);
|
|
166
|
-
}
|
|
167
|
-
function isDate(val) {
|
|
168
|
-
return __toString.call(val) === "[object Date]" || val instanceof Date;
|
|
169
|
-
}
|
|
170
|
-
function tryDecode(str, decode2) {
|
|
171
|
-
try {
|
|
172
|
-
return decode2(str);
|
|
173
|
-
} catch (e) {
|
|
174
|
-
return str;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// src/core.ts
|
|
181
|
-
var import_cookie = __toESM(require_cookie(), 1);
|
|
182
|
-
|
|
183
|
-
// node_modules/.pnpm/iron-webcrypto@1.0.0/node_modules/iron-webcrypto/dist/index.js
|
|
184
|
-
var alphabetByEncoding = {};
|
|
185
|
-
var alphabetByValue = new Array(64);
|
|
186
|
-
for (let i = 0, start = "A".charCodeAt(0), limit = "Z".charCodeAt(0); i + start <= limit; i++) {
|
|
187
|
-
const char = String.fromCharCode(i + start);
|
|
188
|
-
alphabetByEncoding[char] = i;
|
|
189
|
-
alphabetByValue[i] = char;
|
|
190
|
-
}
|
|
191
|
-
for (let i = 0, start = "a".charCodeAt(0), limit = "z".charCodeAt(0); i + start <= limit; i++) {
|
|
192
|
-
const char = String.fromCharCode(i + start);
|
|
193
|
-
const index = i + 26;
|
|
194
|
-
alphabetByEncoding[char] = index;
|
|
195
|
-
alphabetByValue[index] = char;
|
|
196
|
-
}
|
|
197
|
-
for (let i = 0; i < 10; i++) {
|
|
198
|
-
alphabetByEncoding[i.toString(10)] = i + 52;
|
|
199
|
-
const char = i.toString(10);
|
|
200
|
-
const index = i + 52;
|
|
201
|
-
alphabetByEncoding[char] = index;
|
|
202
|
-
alphabetByValue[index] = char;
|
|
203
|
-
}
|
|
204
|
-
alphabetByEncoding["+"] = 62;
|
|
205
|
-
alphabetByValue[62] = "+";
|
|
206
|
-
alphabetByEncoding["/"] = 63;
|
|
207
|
-
alphabetByValue[63] = "/";
|
|
208
|
-
var bitsPerLetter = 6;
|
|
209
|
-
var bitsPerByte = 8;
|
|
210
|
-
var maxLetterValue = 63;
|
|
211
|
-
var fromBase64 = (input) => {
|
|
212
|
-
let totalByteLength = input.length / 4 * 3;
|
|
213
|
-
if (input.slice(-2) === "==") {
|
|
214
|
-
totalByteLength -= 2;
|
|
215
|
-
} else if (input.slice(-1) === "=") {
|
|
216
|
-
totalByteLength--;
|
|
217
|
-
}
|
|
218
|
-
const out = new ArrayBuffer(totalByteLength);
|
|
219
|
-
const dataView = new DataView(out);
|
|
220
|
-
for (let i = 0; i < input.length; i += 4) {
|
|
221
|
-
let bits = 0;
|
|
222
|
-
let bitLength = 0;
|
|
223
|
-
for (let j = i, limit = i + 3; j <= limit; j++) {
|
|
224
|
-
if (input[j] !== "=") {
|
|
225
|
-
if (!(input[j] in alphabetByEncoding)) {
|
|
226
|
-
throw new TypeError(`Invalid character ${input[j]} in base64 string.`);
|
|
227
|
-
}
|
|
228
|
-
bits |= alphabetByEncoding[input[j]] << (limit - j) * bitsPerLetter;
|
|
229
|
-
bitLength += bitsPerLetter;
|
|
230
|
-
} else {
|
|
231
|
-
bits >>= bitsPerLetter;
|
|
7
|
+
function _interopNamespace(e) {
|
|
8
|
+
if (e && e.__esModule) return e;
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
232
18
|
}
|
|
233
|
-
}
|
|
234
|
-
const chunkOffset = i / 4 * 3;
|
|
235
|
-
bits >>= bitLength % bitsPerByte;
|
|
236
|
-
const byteLength = Math.floor(bitLength / bitsPerByte);
|
|
237
|
-
for (let k = 0; k < byteLength; k++) {
|
|
238
|
-
const offset = (byteLength - k - 1) * bitsPerByte;
|
|
239
|
-
dataView.setUint8(chunkOffset + k, (bits & 255 << offset) >> offset);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
return new Uint8Array(out);
|
|
243
|
-
};
|
|
244
|
-
function toBase64(input) {
|
|
245
|
-
let str = "";
|
|
246
|
-
for (let i = 0; i < input.length; i += 3) {
|
|
247
|
-
let bits = 0;
|
|
248
|
-
let bitLength = 0;
|
|
249
|
-
for (let j = i, limit = Math.min(i + 3, input.length); j < limit; j++) {
|
|
250
|
-
bits |= input[j] << (limit - j - 1) * bitsPerByte;
|
|
251
|
-
bitLength += bitsPerByte;
|
|
252
|
-
}
|
|
253
|
-
const bitClusterCount = Math.ceil(bitLength / bitsPerLetter);
|
|
254
|
-
bits <<= bitClusterCount * bitsPerLetter - bitLength;
|
|
255
|
-
for (let k = 1; k <= bitClusterCount; k++) {
|
|
256
|
-
const offset = (bitClusterCount - k) * bitsPerLetter;
|
|
257
|
-
str += alphabetByValue[(bits & maxLetterValue << offset) >> offset];
|
|
258
|
-
}
|
|
259
|
-
str += "==".slice(0, 4 - bitClusterCount);
|
|
19
|
+
});
|
|
260
20
|
}
|
|
261
|
-
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
262
23
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
};
|
|
266
|
-
var bufferToString = (value) => {
|
|
267
|
-
return new TextDecoder().decode(value);
|
|
268
|
-
};
|
|
269
|
-
var base64urlEncode = (value) => toBase64(typeof value === "string" ? stringToBuffer(value) : value).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
270
|
-
var base64urlDecode = (value) => fromBase64(
|
|
271
|
-
value.replace(/-/g, "+").replace(/_/g, "/") + Array((4 - value.length % 4) % 4 + 1).join("=")
|
|
272
|
-
);
|
|
273
|
-
var defaults = {
|
|
274
|
-
encryption: { saltBits: 256, algorithm: "aes-256-cbc", iterations: 1, minPasswordlength: 32 },
|
|
275
|
-
integrity: { saltBits: 256, algorithm: "sha256", iterations: 1, minPasswordlength: 32 },
|
|
276
|
-
ttl: 0,
|
|
277
|
-
timestampSkewSec: 60,
|
|
278
|
-
localtimeOffsetMsec: 0
|
|
279
|
-
};
|
|
280
|
-
var clone = (options) => ({
|
|
281
|
-
...options,
|
|
282
|
-
encryption: { ...options.encryption },
|
|
283
|
-
integrity: { ...options.integrity }
|
|
284
|
-
});
|
|
285
|
-
var algorithms = {
|
|
286
|
-
"aes-128-ctr": { keyBits: 128, ivBits: 128, name: "AES-CTR" },
|
|
287
|
-
"aes-256-cbc": { keyBits: 256, ivBits: 128, name: "AES-CBC" },
|
|
288
|
-
sha256: { keyBits: 256, name: "SHA-256" }
|
|
289
|
-
};
|
|
290
|
-
var macFormatVersion = "2";
|
|
291
|
-
var macPrefix = `Fe26.${macFormatVersion}`;
|
|
292
|
-
var randomBytes = (_crypto, size) => {
|
|
293
|
-
const bytes = new Uint8Array(size);
|
|
294
|
-
_crypto.getRandomValues(bytes);
|
|
295
|
-
return bytes;
|
|
296
|
-
};
|
|
297
|
-
var randomBits = (_crypto, bits) => {
|
|
298
|
-
if (bits < 1)
|
|
299
|
-
throw Error("Invalid random bits count");
|
|
300
|
-
const bytes = Math.ceil(bits / 8);
|
|
301
|
-
return randomBytes(_crypto, bytes);
|
|
302
|
-
};
|
|
303
|
-
var pbkdf2 = async (_crypto, password, salt, iterations, keyLength, hash) => {
|
|
304
|
-
const passwordBuffer = stringToBuffer(password);
|
|
305
|
-
const importedKey = await _crypto.subtle.importKey("raw", passwordBuffer, "PBKDF2", false, [
|
|
306
|
-
"deriveBits"
|
|
307
|
-
]);
|
|
308
|
-
const saltBuffer = stringToBuffer(salt);
|
|
309
|
-
const params = { name: "PBKDF2", hash, salt: saltBuffer, iterations };
|
|
310
|
-
const derivation = await _crypto.subtle.deriveBits(params, importedKey, keyLength * 8);
|
|
311
|
-
return derivation;
|
|
312
|
-
};
|
|
313
|
-
var generateKey = async (_crypto, password, options) => {
|
|
314
|
-
var _a;
|
|
315
|
-
if (!(password == null ? void 0 : password.length))
|
|
316
|
-
throw new Error("Empty password");
|
|
317
|
-
if (options == null || typeof options !== "object")
|
|
318
|
-
throw new Error("Bad options");
|
|
319
|
-
if (!(options.algorithm in algorithms))
|
|
320
|
-
throw new Error(`Unknown algorithm: ${options.algorithm}`);
|
|
321
|
-
const algorithm = algorithms[options.algorithm];
|
|
322
|
-
const result = {};
|
|
323
|
-
const hmac = (_a = options.hmac) != null ? _a : false;
|
|
324
|
-
const id = hmac ? { name: "HMAC", hash: algorithm.name } : { name: algorithm.name };
|
|
325
|
-
const usage = hmac ? ["sign", "verify"] : ["encrypt", "decrypt"];
|
|
326
|
-
if (typeof password === "string") {
|
|
327
|
-
if (password.length < options.minPasswordlength)
|
|
328
|
-
throw new Error(
|
|
329
|
-
`Password string too short (min ${options.minPasswordlength} characters required)`
|
|
330
|
-
);
|
|
331
|
-
let { salt = "" } = options;
|
|
332
|
-
if (!salt) {
|
|
333
|
-
const { saltBits = 0 } = options;
|
|
334
|
-
if (!saltBits)
|
|
335
|
-
throw new Error("Missing salt and saltBits options");
|
|
336
|
-
const randomSalt = randomBits(_crypto, saltBits);
|
|
337
|
-
salt = [...new Uint8Array(randomSalt)].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
338
|
-
}
|
|
339
|
-
const derivedKey = await pbkdf2(
|
|
340
|
-
_crypto,
|
|
341
|
-
password,
|
|
342
|
-
salt,
|
|
343
|
-
options.iterations,
|
|
344
|
-
algorithm.keyBits / 8,
|
|
345
|
-
"SHA-1"
|
|
346
|
-
);
|
|
347
|
-
const importedEncryptionKey = await _crypto.subtle.importKey(
|
|
348
|
-
"raw",
|
|
349
|
-
derivedKey,
|
|
350
|
-
id,
|
|
351
|
-
false,
|
|
352
|
-
usage
|
|
353
|
-
);
|
|
354
|
-
result.key = importedEncryptionKey;
|
|
355
|
-
result.salt = salt;
|
|
356
|
-
} else {
|
|
357
|
-
if (password.length < algorithm.keyBits / 8)
|
|
358
|
-
throw new Error("Key buffer (password) too small");
|
|
359
|
-
result.key = await _crypto.subtle.importKey("raw", password, id, false, usage);
|
|
360
|
-
result.salt = "";
|
|
361
|
-
}
|
|
362
|
-
if (options.iv)
|
|
363
|
-
result.iv = options.iv;
|
|
364
|
-
else if ("ivBits" in algorithm)
|
|
365
|
-
result.iv = randomBits(_crypto, algorithm.ivBits);
|
|
366
|
-
return result;
|
|
367
|
-
};
|
|
368
|
-
var encrypt = async (_crypto, password, options, data) => {
|
|
369
|
-
const key = await generateKey(_crypto, password, options);
|
|
370
|
-
const textBuffer = stringToBuffer(data);
|
|
371
|
-
const encrypted = await _crypto.subtle.encrypt(
|
|
372
|
-
{ name: algorithms[options.algorithm].name, iv: key.iv },
|
|
373
|
-
key.key,
|
|
374
|
-
textBuffer
|
|
375
|
-
);
|
|
376
|
-
return { encrypted: new Uint8Array(encrypted), key };
|
|
377
|
-
};
|
|
378
|
-
var decrypt = async (_crypto, password, options, data) => {
|
|
379
|
-
const key = await generateKey(_crypto, password, options);
|
|
380
|
-
const decrypted = await _crypto.subtle.decrypt(
|
|
381
|
-
{ name: algorithms[options.algorithm].name, iv: key.iv },
|
|
382
|
-
key.key,
|
|
383
|
-
typeof data === "string" ? stringToBuffer(data) : data
|
|
384
|
-
);
|
|
385
|
-
return bufferToString(new Uint8Array(decrypted));
|
|
386
|
-
};
|
|
387
|
-
var hmacWithPassword = async (_crypto, password, options, data) => {
|
|
388
|
-
const key = await generateKey(_crypto, password, { ...options, hmac: true });
|
|
389
|
-
const textBuffer = stringToBuffer(data);
|
|
390
|
-
const signed = await _crypto.subtle.sign({ name: "HMAC" }, key.key, textBuffer);
|
|
391
|
-
const digest = base64urlEncode(new Uint8Array(signed));
|
|
392
|
-
return { digest, salt: key.salt };
|
|
393
|
-
};
|
|
394
|
-
var normalizePassword = (password) => {
|
|
395
|
-
if (typeof password === "string" || password instanceof Uint8Array)
|
|
396
|
-
return { encryption: password, integrity: password };
|
|
397
|
-
if ("secret" in password)
|
|
398
|
-
return { id: password.id, encryption: password.secret, integrity: password.secret };
|
|
399
|
-
return { id: password.id, encryption: password.encryption, integrity: password.integrity };
|
|
400
|
-
};
|
|
401
|
-
var seal = async (_crypto, object, password, options) => {
|
|
402
|
-
if (!password)
|
|
403
|
-
throw Error("Empty password");
|
|
404
|
-
const opts = clone(options);
|
|
405
|
-
const now = Date.now() + (opts.localtimeOffsetMsec || 0);
|
|
406
|
-
const objectString = JSON.stringify(object);
|
|
407
|
-
const pass = normalizePassword(password);
|
|
408
|
-
const { id = "" } = pass;
|
|
409
|
-
if (id && !/^\w+$/.test(id))
|
|
410
|
-
throw new Error("Invalid password id");
|
|
411
|
-
const { encrypted, key } = await encrypt(_crypto, pass.encryption, opts.encryption, objectString);
|
|
412
|
-
const encryptedB64 = base64urlEncode(new Uint8Array(encrypted));
|
|
413
|
-
const iv = base64urlEncode(key.iv);
|
|
414
|
-
const expiration = opts.ttl ? now + opts.ttl : "";
|
|
415
|
-
const macBaseString = `${macPrefix}*${id}*${key.salt}*${iv}*${encryptedB64}*${expiration}`;
|
|
416
|
-
const mac = await hmacWithPassword(_crypto, pass.integrity, opts.integrity, macBaseString);
|
|
417
|
-
const sealed = `${macBaseString}*${mac.salt}*${mac.digest}`;
|
|
418
|
-
return sealed;
|
|
419
|
-
};
|
|
420
|
-
var fixedTimeComparison = (a, b) => {
|
|
421
|
-
let mismatch = a.length === b.length ? 0 : 1;
|
|
422
|
-
if (mismatch)
|
|
423
|
-
b = a;
|
|
424
|
-
for (let i = 0; i < a.length; i += 1)
|
|
425
|
-
mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
426
|
-
return mismatch === 0;
|
|
427
|
-
};
|
|
428
|
-
var unseal = async (_crypto, sealed, password, options) => {
|
|
429
|
-
if (!password)
|
|
430
|
-
throw Error("Empty password");
|
|
431
|
-
const opts = clone(options);
|
|
432
|
-
const now = Date.now() + (opts.localtimeOffsetMsec || 0);
|
|
433
|
-
const parts = sealed.split("*");
|
|
434
|
-
if (parts.length !== 8)
|
|
435
|
-
throw new Error("Incorrect number of sealed components");
|
|
436
|
-
const prefix = parts[0];
|
|
437
|
-
let passwordId = parts[1];
|
|
438
|
-
const encryptionSalt = parts[2];
|
|
439
|
-
const encryptionIv = parts[3];
|
|
440
|
-
const encryptedB64 = parts[4];
|
|
441
|
-
const expiration = parts[5];
|
|
442
|
-
const hmacSalt = parts[6];
|
|
443
|
-
const hmac = parts[7];
|
|
444
|
-
const macBaseString = `${prefix}*${passwordId}*${encryptionSalt}*${encryptionIv}*${encryptedB64}*${expiration}`;
|
|
445
|
-
if (macPrefix !== prefix)
|
|
446
|
-
throw new Error("Wrong mac prefix");
|
|
447
|
-
if (expiration) {
|
|
448
|
-
if (!/^\d+$/.exec(expiration))
|
|
449
|
-
throw new Error("Invalid expiration");
|
|
450
|
-
const exp = parseInt(expiration, 10);
|
|
451
|
-
if (exp <= now - opts.timestampSkewSec * 1e3)
|
|
452
|
-
throw new Error("Expired seal");
|
|
453
|
-
}
|
|
454
|
-
if (typeof password === "undefined" || typeof password === "string" && password.length === 0)
|
|
455
|
-
throw new Error("Empty password");
|
|
456
|
-
let pass = "";
|
|
457
|
-
passwordId = passwordId || "default";
|
|
458
|
-
if (typeof password === "string" || password instanceof Uint8Array)
|
|
459
|
-
pass = password;
|
|
460
|
-
else if (!(passwordId in password))
|
|
461
|
-
throw new Error(`Cannot find password: ${passwordId}`);
|
|
462
|
-
else
|
|
463
|
-
pass = password[passwordId];
|
|
464
|
-
pass = normalizePassword(pass);
|
|
465
|
-
const macOptions = opts.integrity;
|
|
466
|
-
macOptions.salt = hmacSalt;
|
|
467
|
-
const mac = await hmacWithPassword(_crypto, pass.integrity, macOptions, macBaseString);
|
|
468
|
-
if (!fixedTimeComparison(mac.digest, hmac))
|
|
469
|
-
throw new Error("Bad hmac value");
|
|
470
|
-
const encrypted = base64urlDecode(encryptedB64);
|
|
471
|
-
const decryptOptions = opts.encryption;
|
|
472
|
-
decryptOptions.salt = encryptionSalt;
|
|
473
|
-
decryptOptions.iv = base64urlDecode(encryptionIv);
|
|
474
|
-
const decrypted = await decrypt(_crypto, pass.encryption, decryptOptions, encrypted);
|
|
475
|
-
if (decrypted)
|
|
476
|
-
return JSON.parse(decrypted);
|
|
477
|
-
return null;
|
|
478
|
-
};
|
|
24
|
+
|
|
25
|
+
var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
|
|
479
26
|
|
|
480
27
|
// src/core.ts
|
|
481
28
|
var timestampSkewSec = 60;
|
|
@@ -489,8 +36,8 @@ var defaultOptions = {
|
|
|
489
36
|
function normalizeStringPasswordToMap(password) {
|
|
490
37
|
return typeof password === "string" ? { 1: password } : password;
|
|
491
38
|
}
|
|
492
|
-
function parseSeal(
|
|
493
|
-
const [sealWithoutVersion, tokenVersionAsString] =
|
|
39
|
+
function parseSeal(seal) {
|
|
40
|
+
const [sealWithoutVersion, tokenVersionAsString] = seal.split(versionDelimiter);
|
|
494
41
|
const tokenVersion = tokenVersionAsString == null ? null : parseInt(tokenVersionAsString, 10);
|
|
495
42
|
return { sealWithoutVersion, tokenVersion };
|
|
496
43
|
}
|
|
@@ -501,7 +48,7 @@ function computeCookieMaxAge(ttl) {
|
|
|
501
48
|
return ttl - timestampSkewSec;
|
|
502
49
|
}
|
|
503
50
|
function getCookie(req, cookieName) {
|
|
504
|
-
return
|
|
51
|
+
return cookie.parse(
|
|
505
52
|
("headers" in req && typeof req.headers.get === "function" ? req.headers.get("cookie") : req.headers.cookie) ?? ""
|
|
506
53
|
)[cookieName] ?? "";
|
|
507
54
|
}
|
|
@@ -527,7 +74,7 @@ function setCookie(res, cookieValue) {
|
|
|
527
74
|
cookieValue
|
|
528
75
|
]);
|
|
529
76
|
}
|
|
530
|
-
function createSealData(_crypto
|
|
77
|
+
function createSealData(_crypto) {
|
|
531
78
|
return async function sealData2(data, {
|
|
532
79
|
password,
|
|
533
80
|
ttl = fourteenDaysInSeconds
|
|
@@ -541,23 +88,23 @@ function createSealData(_crypto = globalThis.crypto ??= __require("crypto").webc
|
|
|
541
88
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
542
89
|
secret: passwordsMap[mostRecentPasswordId]
|
|
543
90
|
};
|
|
544
|
-
const
|
|
545
|
-
...defaults,
|
|
91
|
+
const seal = await ironWebcrypto.seal(_crypto, data, passwordForSeal, {
|
|
92
|
+
...ironWebcrypto.defaults,
|
|
546
93
|
ttl: ttl * 1e3
|
|
547
94
|
});
|
|
548
|
-
return `${
|
|
95
|
+
return `${seal}${versionDelimiter}${currentMajorVersion}`;
|
|
549
96
|
};
|
|
550
97
|
}
|
|
551
|
-
function createUnsealData(_crypto
|
|
552
|
-
return async function unsealData2(
|
|
98
|
+
function createUnsealData(_crypto) {
|
|
99
|
+
return async function unsealData2(seal, {
|
|
553
100
|
password,
|
|
554
101
|
ttl = fourteenDaysInSeconds
|
|
555
102
|
}) {
|
|
556
103
|
const passwordsMap = normalizeStringPasswordToMap(password);
|
|
557
|
-
const { sealWithoutVersion, tokenVersion } = parseSeal(
|
|
104
|
+
const { sealWithoutVersion, tokenVersion } = parseSeal(seal);
|
|
558
105
|
try {
|
|
559
|
-
const data = await unseal(_crypto, sealWithoutVersion, passwordsMap, {
|
|
560
|
-
...defaults,
|
|
106
|
+
const data = await ironWebcrypto.unseal(_crypto, sealWithoutVersion, passwordsMap, {
|
|
107
|
+
...ironWebcrypto.defaults,
|
|
561
108
|
ttl: ttl * 1e3
|
|
562
109
|
}) ?? {};
|
|
563
110
|
if (tokenVersion === 2) {
|
|
@@ -634,13 +181,13 @@ function createGetIronSession(sealData2, unsealData2) {
|
|
|
634
181
|
);
|
|
635
182
|
}
|
|
636
183
|
const mergedOptions = mergeOptions(userSessionOptions, saveOptions);
|
|
637
|
-
const
|
|
184
|
+
const seal = await sealData2(session, {
|
|
638
185
|
password: passwordsMap,
|
|
639
186
|
ttl: mergedOptions.ttl
|
|
640
187
|
});
|
|
641
|
-
const cookieValue =
|
|
188
|
+
const cookieValue = cookie.serialize(
|
|
642
189
|
mergedOptions.cookieName,
|
|
643
|
-
|
|
190
|
+
seal,
|
|
644
191
|
mergedOptions.cookieOptions
|
|
645
192
|
);
|
|
646
193
|
if (cookieValue.length > 4096) {
|
|
@@ -660,7 +207,7 @@ function createGetIronSession(sealData2, unsealData2) {
|
|
|
660
207
|
userSessionOptions,
|
|
661
208
|
destroyOptions
|
|
662
209
|
);
|
|
663
|
-
const cookieValue =
|
|
210
|
+
const cookieValue = cookie.serialize(mergedOptions.cookieName, "", {
|
|
664
211
|
...mergedOptions.cookieOptions,
|
|
665
212
|
maxAge: 0
|
|
666
213
|
});
|
|
@@ -708,11 +255,11 @@ function createGetServerActionIronSession(sealData2, unsealData2) {
|
|
|
708
255
|
save: {
|
|
709
256
|
value: async function save(saveOptions) {
|
|
710
257
|
const mergedOptions = mergeOptions(userSessionOptions, saveOptions);
|
|
711
|
-
const
|
|
258
|
+
const seal = await sealData2(session, {
|
|
712
259
|
password: passwordsMap,
|
|
713
260
|
ttl: mergedOptions.ttl
|
|
714
261
|
});
|
|
715
|
-
const cookieLength = mergedOptions.cookieName.length +
|
|
262
|
+
const cookieLength = mergedOptions.cookieName.length + seal.length + JSON.stringify(mergedOptions.cookieOptions).length;
|
|
716
263
|
if (cookieLength > 4096) {
|
|
717
264
|
throw new Error(
|
|
718
265
|
`iron-session: Cookie length is too big (${cookieLength} bytes), browsers will refuse it. Try to remove some data.`
|
|
@@ -720,7 +267,7 @@ function createGetServerActionIronSession(sealData2, unsealData2) {
|
|
|
720
267
|
}
|
|
721
268
|
cookieHandler.set(
|
|
722
269
|
mergedOptions.cookieName,
|
|
723
|
-
|
|
270
|
+
seal,
|
|
724
271
|
mergedOptions.cookieOptions
|
|
725
272
|
);
|
|
726
273
|
}
|
|
@@ -758,25 +305,13 @@ function createResponse(originalResponse, bodyString, options) {
|
|
|
758
305
|
headers: mergeHeaders(options?.headers, originalResponse.headers)
|
|
759
306
|
});
|
|
760
307
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
var sealData = createSealData();
|
|
764
|
-
var unsealData = createUnsealData();
|
|
308
|
+
var sealData = createSealData(crypto__namespace);
|
|
309
|
+
var unsealData = createUnsealData(crypto__namespace);
|
|
765
310
|
var getIronSession = createGetIronSession(sealData, unsealData);
|
|
766
311
|
var getServerActionIronSession = createGetServerActionIronSession(
|
|
767
312
|
sealData,
|
|
768
313
|
unsealData
|
|
769
314
|
);
|
|
770
|
-
/*! Bundled license information:
|
|
771
|
-
|
|
772
|
-
cookie/index.js:
|
|
773
|
-
(*!
|
|
774
|
-
* cookie
|
|
775
|
-
* Copyright(c) 2012-2014 Roman Shtylman
|
|
776
|
-
* Copyright(c) 2015 Douglas Christopher Wilson
|
|
777
|
-
* MIT Licensed
|
|
778
|
-
*)
|
|
779
|
-
*/
|
|
780
315
|
|
|
781
316
|
exports.createGetIronSession = createGetIronSession;
|
|
782
317
|
exports.createGetServerActionIronSession = createGetServerActionIronSession;
|