@thunderid/node 1.0.3 → 1.0.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/cjs/index.cjs +67 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +67 -1
- package/dist/utils/CookieChunking.d.ts +43 -0
- package/dist/utils/CookieChunking.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -276,6 +276,72 @@ var CookieConfig = class CookieConfig {
|
|
|
276
276
|
};
|
|
277
277
|
var CookieConfig_default = CookieConfig;
|
|
278
278
|
|
|
279
|
+
//#endregion
|
|
280
|
+
//#region src/utils/CookieChunking.ts
|
|
281
|
+
/**
|
|
282
|
+
* Framework-agnostic cookie chunking. Browsers reject a `Set-Cookie` once
|
|
283
|
+
* the full `name=value; attributes` line exceeds ~4096 bytes, so a session
|
|
284
|
+
* cookie carrying a JWT (access/id/refresh tokens) can overflow that limit.
|
|
285
|
+
* Mirrors next-auth's session cookie chunking (packages/core/src/lib/utils/cookie.ts):
|
|
286
|
+
* split an oversized value across numbered `${name}.0`, `${name}.1`, ...
|
|
287
|
+
* cookies and reassemble on read.
|
|
288
|
+
*
|
|
289
|
+
* This class only computes chunk names/values — reading, writing, and
|
|
290
|
+
* deleting cookies is framework-specific (h3, Next.js, Express, ...), so
|
|
291
|
+
* callers plug in their own cookie access via the `getCookie` callback and
|
|
292
|
+
* by writing/deleting the names this class returns.
|
|
293
|
+
*/
|
|
294
|
+
var CookieChunking = class CookieChunking {
|
|
295
|
+
constructor() {}
|
|
296
|
+
static ALLOWED_COOKIE_SIZE = 4096;
|
|
297
|
+
static ESTIMATED_EMPTY_COOKIE_SIZE = 160;
|
|
298
|
+
static CHUNK_SIZE = CookieChunking.ALLOWED_COOKIE_SIZE - CookieChunking.ESTIMATED_EMPTY_COOKIE_SIZE;
|
|
299
|
+
/**
|
|
300
|
+
* Builds the cookie name for chunk `index` of a chunked cookie `name`.
|
|
301
|
+
*/
|
|
302
|
+
static getChunkName(name, index) {
|
|
303
|
+
return `${name}.${index}`;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Filters `cookieNames` down to those belonging to `name`: the unchunked
|
|
307
|
+
* base cookie and/or any numbered `${name}.0`, `${name}.1`, ... chunks.
|
|
308
|
+
*/
|
|
309
|
+
static filterChunkNames(name, cookieNames) {
|
|
310
|
+
const prefix = `${name}.`;
|
|
311
|
+
return cookieNames.filter((cookieName) => cookieName === name || cookieName.startsWith(prefix));
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Splits `value` into the cookie name/value pairs that should be written
|
|
315
|
+
* for `name`: a single `{[name]: value}` entry when it fits in one
|
|
316
|
+
* cookie, or numbered `${name}.0`, `${name}.1`, ... entries once it would
|
|
317
|
+
* exceed the ~4KB per-cookie limit.
|
|
318
|
+
*/
|
|
319
|
+
static split(name, value) {
|
|
320
|
+
const chunkCount = Math.max(1, Math.ceil(value.length / CookieChunking.CHUNK_SIZE));
|
|
321
|
+
if (chunkCount === 1) return { [name]: value };
|
|
322
|
+
const chunks = {};
|
|
323
|
+
for (let i = 0; i < chunkCount; i += 1) chunks[CookieChunking.getChunkName(name, i)] = value.slice(i * CookieChunking.CHUNK_SIZE, (i + 1) * CookieChunking.CHUNK_SIZE);
|
|
324
|
+
return chunks;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Reassembles a cookie value that may have been split via {@link split}.
|
|
328
|
+
* Calls `getCookie` with `name` first, then `${name}.0`, `${name}.1`, ...
|
|
329
|
+
* until a lookup returns `undefined`.
|
|
330
|
+
*/
|
|
331
|
+
static join(name, getCookie) {
|
|
332
|
+
const unchunked = getCookie(name);
|
|
333
|
+
if (unchunked !== void 0) return unchunked;
|
|
334
|
+
const chunks = [];
|
|
335
|
+
for (let i = 0;; i += 1) {
|
|
336
|
+
const chunk = getCookie(CookieChunking.getChunkName(name, i));
|
|
337
|
+
if (chunk === void 0) break;
|
|
338
|
+
chunks.push(chunk);
|
|
339
|
+
}
|
|
340
|
+
return chunks.length > 0 ? chunks.join("") : void 0;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
var CookieChunking_default = CookieChunking;
|
|
344
|
+
|
|
279
345
|
//#endregion
|
|
280
346
|
//#region src/utils/generateSessionId.ts
|
|
281
347
|
const generateSessionId = () => (/* @__PURE__ */ new Date()).getTime().toString(36) + Math.random().toString(36).substring(2);
|
|
@@ -300,6 +366,7 @@ if (!globalThis.fetch) {
|
|
|
300
366
|
}
|
|
301
367
|
|
|
302
368
|
//#endregion
|
|
369
|
+
exports.CookieChunking = CookieChunking_default;
|
|
303
370
|
exports.CookieConfig = CookieConfig_default;
|
|
304
371
|
exports.MemoryCacheStore = MemoryCacheStore_default;
|
|
305
372
|
exports.NodeCryptoUtils = NodeCryptoUtils_default;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { default as CookieConfig } from './constants/CookieConfig';
|
|
|
6
6
|
export type { ThunderIDNodeConfig, SessionCookieConfig } from './models/config';
|
|
7
7
|
export type { default as AuthURLCallback } from './models/AuthURLCallback';
|
|
8
8
|
export { default as MemoryCacheStore } from './stores/MemoryCacheStore';
|
|
9
|
+
export { default as CookieChunking } from './utils/CookieChunking';
|
|
9
10
|
export { default as NodeCryptoUtils } from './utils/NodeCryptoUtils';
|
|
10
11
|
export { default as SessionUtils } from './utils/SessionUtils';
|
|
11
12
|
export { default as generateSessionId } from './utils/generateSessionId';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA;;GAEG;AAGH,OAAO,EAAC,OAAO,IAAI,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAC,OAAO,IAAI,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAGjE,YAAY,EAAC,mBAAmB,EAAE,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAC9E,YAAY,EAAC,OAAO,IAAI,eAAe,EAAC,MAAM,0BAA0B,CAAC;AAGzE,OAAO,EAAC,OAAO,IAAI,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAGtE,OAAO,EAAC,OAAO,IAAI,eAAe,EAAC,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAC,OAAO,IAAI,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAC,OAAO,IAAI,iBAAiB,EAAC,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAC,OAAO,IAAI,uBAAuB,EAAC,MAAM,iCAAiC,CAAC;AAGnF,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA;;GAEG;AAGH,OAAO,EAAC,OAAO,IAAI,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAC,OAAO,IAAI,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAGjE,YAAY,EAAC,mBAAmB,EAAE,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAC9E,YAAY,EAAC,OAAO,IAAI,eAAe,EAAC,MAAM,0BAA0B,CAAC;AAGzE,OAAO,EAAC,OAAO,IAAI,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAGtE,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAC,OAAO,IAAI,eAAe,EAAC,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAC,OAAO,IAAI,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAC,OAAO,IAAI,iBAAiB,EAAC,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAC,OAAO,IAAI,uBAAuB,EAAC,MAAM,iCAAiC,CAAC;AAGnF,cAAc,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -247,6 +247,72 @@ var CookieConfig = class CookieConfig {
|
|
|
247
247
|
};
|
|
248
248
|
var CookieConfig_default = CookieConfig;
|
|
249
249
|
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/utils/CookieChunking.ts
|
|
252
|
+
/**
|
|
253
|
+
* Framework-agnostic cookie chunking. Browsers reject a `Set-Cookie` once
|
|
254
|
+
* the full `name=value; attributes` line exceeds ~4096 bytes, so a session
|
|
255
|
+
* cookie carrying a JWT (access/id/refresh tokens) can overflow that limit.
|
|
256
|
+
* Mirrors next-auth's session cookie chunking (packages/core/src/lib/utils/cookie.ts):
|
|
257
|
+
* split an oversized value across numbered `${name}.0`, `${name}.1`, ...
|
|
258
|
+
* cookies and reassemble on read.
|
|
259
|
+
*
|
|
260
|
+
* This class only computes chunk names/values — reading, writing, and
|
|
261
|
+
* deleting cookies is framework-specific (h3, Next.js, Express, ...), so
|
|
262
|
+
* callers plug in their own cookie access via the `getCookie` callback and
|
|
263
|
+
* by writing/deleting the names this class returns.
|
|
264
|
+
*/
|
|
265
|
+
var CookieChunking = class CookieChunking {
|
|
266
|
+
constructor() {}
|
|
267
|
+
static ALLOWED_COOKIE_SIZE = 4096;
|
|
268
|
+
static ESTIMATED_EMPTY_COOKIE_SIZE = 160;
|
|
269
|
+
static CHUNK_SIZE = CookieChunking.ALLOWED_COOKIE_SIZE - CookieChunking.ESTIMATED_EMPTY_COOKIE_SIZE;
|
|
270
|
+
/**
|
|
271
|
+
* Builds the cookie name for chunk `index` of a chunked cookie `name`.
|
|
272
|
+
*/
|
|
273
|
+
static getChunkName(name, index) {
|
|
274
|
+
return `${name}.${index}`;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Filters `cookieNames` down to those belonging to `name`: the unchunked
|
|
278
|
+
* base cookie and/or any numbered `${name}.0`, `${name}.1`, ... chunks.
|
|
279
|
+
*/
|
|
280
|
+
static filterChunkNames(name, cookieNames) {
|
|
281
|
+
const prefix = `${name}.`;
|
|
282
|
+
return cookieNames.filter((cookieName) => cookieName === name || cookieName.startsWith(prefix));
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Splits `value` into the cookie name/value pairs that should be written
|
|
286
|
+
* for `name`: a single `{[name]: value}` entry when it fits in one
|
|
287
|
+
* cookie, or numbered `${name}.0`, `${name}.1`, ... entries once it would
|
|
288
|
+
* exceed the ~4KB per-cookie limit.
|
|
289
|
+
*/
|
|
290
|
+
static split(name, value) {
|
|
291
|
+
const chunkCount = Math.max(1, Math.ceil(value.length / CookieChunking.CHUNK_SIZE));
|
|
292
|
+
if (chunkCount === 1) return { [name]: value };
|
|
293
|
+
const chunks = {};
|
|
294
|
+
for (let i = 0; i < chunkCount; i += 1) chunks[CookieChunking.getChunkName(name, i)] = value.slice(i * CookieChunking.CHUNK_SIZE, (i + 1) * CookieChunking.CHUNK_SIZE);
|
|
295
|
+
return chunks;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Reassembles a cookie value that may have been split via {@link split}.
|
|
299
|
+
* Calls `getCookie` with `name` first, then `${name}.0`, `${name}.1`, ...
|
|
300
|
+
* until a lookup returns `undefined`.
|
|
301
|
+
*/
|
|
302
|
+
static join(name, getCookie) {
|
|
303
|
+
const unchunked = getCookie(name);
|
|
304
|
+
if (unchunked !== void 0) return unchunked;
|
|
305
|
+
const chunks = [];
|
|
306
|
+
for (let i = 0;; i += 1) {
|
|
307
|
+
const chunk = getCookie(CookieChunking.getChunkName(name, i));
|
|
308
|
+
if (chunk === void 0) break;
|
|
309
|
+
chunks.push(chunk);
|
|
310
|
+
}
|
|
311
|
+
return chunks.length > 0 ? chunks.join("") : void 0;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
var CookieChunking_default = CookieChunking;
|
|
315
|
+
|
|
250
316
|
//#endregion
|
|
251
317
|
//#region src/utils/generateSessionId.ts
|
|
252
318
|
const generateSessionId = () => (/* @__PURE__ */ new Date()).getTime().toString(36) + Math.random().toString(36).substring(2);
|
|
@@ -271,4 +337,4 @@ if (!globalThis.fetch) {
|
|
|
271
337
|
}
|
|
272
338
|
|
|
273
339
|
//#endregion
|
|
274
|
-
export { CookieConfig_default as CookieConfig, MemoryCacheStore_default as MemoryCacheStore, NodeCryptoUtils_default as NodeCryptoUtils, SessionUtils_default as SessionUtils, ThunderIDNodeClient_default as ThunderIDNodeClient, generateSessionId_default as generateSessionId, getSessionCookieOptions_default as getSessionCookieOptions };
|
|
340
|
+
export { CookieChunking_default as CookieChunking, CookieConfig_default as CookieConfig, MemoryCacheStore_default as MemoryCacheStore, NodeCryptoUtils_default as NodeCryptoUtils, SessionUtils_default as SessionUtils, ThunderIDNodeClient_default as ThunderIDNodeClient, generateSessionId_default as generateSessionId, getSessionCookieOptions_default as getSessionCookieOptions };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic cookie chunking. Browsers reject a `Set-Cookie` once
|
|
3
|
+
* the full `name=value; attributes` line exceeds ~4096 bytes, so a session
|
|
4
|
+
* cookie carrying a JWT (access/id/refresh tokens) can overflow that limit.
|
|
5
|
+
* Mirrors next-auth's session cookie chunking (packages/core/src/lib/utils/cookie.ts):
|
|
6
|
+
* split an oversized value across numbered `${name}.0`, `${name}.1`, ...
|
|
7
|
+
* cookies and reassemble on read.
|
|
8
|
+
*
|
|
9
|
+
* This class only computes chunk names/values — reading, writing, and
|
|
10
|
+
* deleting cookies is framework-specific (h3, Next.js, Express, ...), so
|
|
11
|
+
* callers plug in their own cookie access via the `getCookie` callback and
|
|
12
|
+
* by writing/deleting the names this class returns.
|
|
13
|
+
*/
|
|
14
|
+
declare class CookieChunking {
|
|
15
|
+
private constructor();
|
|
16
|
+
static readonly ALLOWED_COOKIE_SIZE: number;
|
|
17
|
+
static readonly ESTIMATED_EMPTY_COOKIE_SIZE: number;
|
|
18
|
+
static readonly CHUNK_SIZE: number;
|
|
19
|
+
/**
|
|
20
|
+
* Builds the cookie name for chunk `index` of a chunked cookie `name`.
|
|
21
|
+
*/
|
|
22
|
+
static getChunkName(name: string, index: number): string;
|
|
23
|
+
/**
|
|
24
|
+
* Filters `cookieNames` down to those belonging to `name`: the unchunked
|
|
25
|
+
* base cookie and/or any numbered `${name}.0`, `${name}.1`, ... chunks.
|
|
26
|
+
*/
|
|
27
|
+
static filterChunkNames(name: string, cookieNames: string[]): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Splits `value` into the cookie name/value pairs that should be written
|
|
30
|
+
* for `name`: a single `{[name]: value}` entry when it fits in one
|
|
31
|
+
* cookie, or numbered `${name}.0`, `${name}.1`, ... entries once it would
|
|
32
|
+
* exceed the ~4KB per-cookie limit.
|
|
33
|
+
*/
|
|
34
|
+
static split(name: string, value: string): Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* Reassembles a cookie value that may have been split via {@link split}.
|
|
37
|
+
* Calls `getCookie` with `name` first, then `${name}.0`, `${name}.1`, ...
|
|
38
|
+
* until a lookup returns `undefined`.
|
|
39
|
+
*/
|
|
40
|
+
static join(name: string, getCookie: (cookieName: string) => string | undefined): string | undefined;
|
|
41
|
+
}
|
|
42
|
+
export default CookieChunking;
|
|
43
|
+
//# sourceMappingURL=CookieChunking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CookieChunking.d.ts","sourceRoot":"","sources":["../../src/utils/CookieChunking.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,cAAM,cAAc;IAElB,OAAO;IAEP,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAQ;IAEnD,MAAM,CAAC,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAO;IAE1D,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAmF;IAErH;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAIxD;;;OAGG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IAKtE;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAiBjE;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;CAarG;AAED,eAAe,cAAc,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thunderid/node",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Node.js runtime SDK for ThunderID",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"thunderid",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"secure-random-bytes": "5.0.1",
|
|
53
53
|
"tslib": "2.8.1",
|
|
54
54
|
"uuid": "11.1.1",
|
|
55
|
-
"@thunderid/javascript": "^1.0.
|
|
55
|
+
"@thunderid/javascript": "^1.0.5"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|