unjwt 0.7.2 → 0.8.0

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 (39) hide show
  1. package/README.md +4 -4
  2. package/dist/THIRD-PARTY-LICENSES.md.gz +0 -0
  3. package/dist/_chunks/_codec-jwe.d.mts +170 -0
  4. package/dist/_chunks/_codec-jws.mjs +878 -0
  5. package/dist/_chunks/_internal.d.mts +7 -0
  6. package/dist/_chunks/_jwt-internal.mjs +388 -0
  7. package/dist/_chunks/algorithms.mjs +186 -0
  8. package/dist/_chunks/index.d.mts +512 -818
  9. package/dist/_chunks/index2.d.mts +11 -0
  10. package/dist/_chunks/index3.d.mts +108 -0
  11. package/dist/_chunks/jwe.d.mts +43 -66
  12. package/dist/_chunks/jwe.mjs +384 -252
  13. package/dist/_chunks/jwk.mjs +1390 -622
  14. package/dist/_chunks/jws.d.mts +48 -103
  15. package/dist/_chunks/jws.mjs +372 -184
  16. package/dist/_chunks/jwt.d.mts +56 -0
  17. package/dist/_chunks/libs/unsecure.d.mts +164 -85
  18. package/dist/_chunks/libs/unsecure.mjs +390 -123
  19. package/dist/adapters/elysia/index.d.mts +33 -171
  20. package/dist/adapters/elysia/index.mjs +106 -575
  21. package/dist/adapters/h3v1/index.d.mts +59 -344
  22. package/dist/adapters/h3v1/index.mjs +114 -619
  23. package/dist/adapters/h3v2/index.d.mts +58 -326
  24. package/dist/adapters/h3v2/index.mjs +108 -611
  25. package/dist/core/internal.d.mts +2 -0
  26. package/dist/core/internal.mjs +1 -0
  27. package/dist/core/jwe.d.mts +4 -2
  28. package/dist/core/jwe.mjs +4 -2
  29. package/dist/core/jwk.d.mts +183 -371
  30. package/dist/core/jwk.mjs +4 -3
  31. package/dist/core/jws.d.mts +4 -2
  32. package/dist/core/jws.mjs +4 -2
  33. package/dist/core/utils/index.d.mts +5 -155
  34. package/dist/core/utils/index.mjs +12 -3
  35. package/dist/index.d.mts +8 -4
  36. package/dist/index.mjs +6 -3
  37. package/package.json +39 -36
  38. package/dist/_chunks/_internal.mjs +0 -88
  39. package/dist/_chunks/utils.mjs +0 -390
@@ -0,0 +1,56 @@
1
+ import { Duration, JOSEPayloadMode, JWTClaimValidationOptions, JWTClaims, JWTErrorCode, JWTTimeClaimOptions, PayloadOf } from "./index.mjs";
2
+ /** Set `typ: "JWT"` on a header without `typ` when the payload is an object (not a `Uint8Array`). */
3
+ export declare function applyTypDefault<T extends {
4
+ typ?: string;
5
+ }>(header: T, payload: unknown): T;
6
+ /** Options for {@link parsePayloadBytes} and {@link parsePayloadSegment}. */
7
+ export interface ParsePayloadOptions<Mode extends JOSEPayloadMode = JOSEPayloadMode> {
8
+ /** How to interpret the payload bytes; the return type follows it. @default "json" */
9
+ payload?: Mode;
10
+ /** Family the rejection is reported under (`ERR_JWS_INVALID` / `ERR_JWE_INVALID`). @default "JWS" */
11
+ family?: "JWS" | "JWE";
12
+ }
13
+ /** Parse payload bytes under the declared mode: `"json"` needs a UTF-8 JSON object, `"string"` UTF-8; throws `ERR_JWS_INVALID` / `ERR_JWE_INVALID`. */
14
+ export declare function parsePayloadBytes<T = JWTClaims>(bytes: Uint8Array<ArrayBuffer>, options?: ParsePayloadOptions<"json">): T;
15
+ export declare function parsePayloadBytes<Mode extends JOSEPayloadMode = JOSEPayloadMode>(bytes: Uint8Array<ArrayBuffer>, options?: ParsePayloadOptions<Mode>): PayloadOf<Mode>;
16
+ /** Decode payload bytes as UTF-8; throws `ERR_JWS_INVALID` / `ERR_JWE_INVALID` otherwise. */
17
+ export declare function parsePayloadText(bytes: Uint8Array<ArrayBuffer>, options?: Pick<ParsePayloadOptions, "family">): string;
18
+ /** {@link parsePayloadBytes} over a Base64URL-encoded payload segment. */
19
+ export declare function parsePayloadSegment<T = JWTClaims>(payloadEncoded: string, options?: ParsePayloadOptions<"json">): T;
20
+ export declare function parsePayloadSegment<Mode extends JOSEPayloadMode = JOSEPayloadMode>(payloadEncoded: string, options?: ParsePayloadOptions<Mode>): PayloadOf<Mode>;
21
+ /** Encode a payload to bytes; a non-serializable one throws `ERR_INVALID_OPTION`. */
22
+ export declare function getPlaintextBytes(payload: string | Uint8Array<ArrayBuffer> | Record<string, unknown>): Uint8Array<ArrayBuffer>;
23
+ /** Options for {@link computeJwtTimeClaims}. */
24
+ export type ComputeJwtTimeClaimsOptions = JWTTimeClaimOptions;
25
+ /**
26
+ * Return a copy of an object payload with `iat` and the requested `exp` / `nbf`, or `undefined` when none applies.
27
+ * Both members of `expiresIn`/`expiresAt` or `notBeforeIn`/`notBeforeAt` throw `ERR_JWT_CLAIM_INVALID`.
28
+ */
29
+ export declare function computeJwtTimeClaims(payload: unknown, options?: ComputeJwtTimeClaimsOptions): JWTClaims | undefined;
30
+ /** Validate critical headers in JWS semantics. */
31
+ export declare function validateCriticalHeadersJWS(protectedHeader: {
32
+ crit?: string[];
33
+ } & Record<string, unknown>, recognizedHeaders?: string[]): void;
34
+ /** Validate critical headers in JWE semantics. */
35
+ export declare function validateCriticalHeadersJWE(protectedHeader: {
36
+ crit?: string[];
37
+ } & Record<string, unknown>, recognizedHeaders?: string[]): void;
38
+ /** Assert `crit` is a non-empty string array with no registered header name (RFC 7515 §4.1.11 / RFC 7516 §4.1.13). */
39
+ export declare function assertCritShape(crit: unknown, options: {
40
+ family: "JWS" | "JWE";
41
+ code?: JWTErrorCode;
42
+ }): asserts crit is string[];
43
+ /** Whether headers declare JSON content: a string `typ` naming JWT, or a JSON `cty`. */
44
+ export declare function isJWTContent(header: {
45
+ typ?: string;
46
+ cty?: string;
47
+ } | undefined): boolean;
48
+ /** Parse a `Duration` (e.g. `3600` or `"10m"`) into positive integer seconds; else `ERR_INVALID_OPTION`. */
49
+ export declare function computeDurationInSeconds(duration: Duration): number;
50
+ /** The `ERR_JWT_EXPIRED` message for a token whose `exp` (NumericDate seconds) has passed. */
51
+ export declare function expiredClaimMessage(exp: number): string;
52
+ /**
53
+ * Validate JWT claims against the set expectations. A malformed expectation throws
54
+ * `ERR_INVALID_OPTION`; an empty `audience` or `issuer` list matches no token.
55
+ */
56
+ export declare function validateJwtClaims(jwtClaims: JWTClaims, options?: JWTClaimValidationOptions): void;
@@ -1,94 +1,173 @@
1
1
  /**
2
- * Generate a Uint8Array of cryptographically secure random bytes.
3
- *
4
- * @param length Number of random bytes to generate.
5
- * @returns A Uint8Array filled with random bytes.
6
- *
7
- * @example
8
- * const key = secureRandomBytes(32); // 256-bit key material
9
- */
10
- declare function secureRandomBytes(length: number): Uint8Array<ArrayBuffer>;
2
+ * What kind of mistake an {@link UnsecureError} reports.
3
+ *
4
+ * This is the complete set for this release, so a `switch` over it is
5
+ * exhaustive today. A later minor may add a member — keep a default branch, or
6
+ * a new code will fall through unhandled.
7
+ *
8
+ * - `INVALID_TYPE` — a value of the wrong JavaScript type, or nothing where a
9
+ * value is required.
10
+ * - `OUT_OF_RANGE` — the right type, outside its documented domain: a number
11
+ * past its bounds, an empty secret, an alphabet that is not 32 distinct
12
+ * ASCII characters, no character set selected.
13
+ * - `MALFORMED` — text that is not what it claims to be: a non-canonical
14
+ * encoding, decoded bytes that are not valid UTF-8, JSON that does not parse.
15
+ * - `UNSUPPORTED` — a name outside the set the library accepts: a digest
16
+ * algorithm, a `returnAs`, an `otpauthURI` `type`.
17
+ * - `FROZEN` — a dangerous key cannot be removed because the object holding it
18
+ * is frozen or sealed.
19
+ * - `PLATFORM` — the runtime's Web Crypto refused an operation the library had
20
+ * already validated; `cause` carries the platform error.
21
+ */
22
+ export type UnsecureErrorCode = "INVALID_TYPE" | "OUT_OF_RANGE" | "MALFORMED" | "UNSUPPORTED" | "FROZEN" | "PLATFORM";
11
23
  /**
12
- * Shuffles an array in-place using the Fisher-Yates algorithm with a
13
- * cryptographically secure random number generator.
14
- * @template T
15
- * @param {Array<T>} array The array to shuffle.
16
- * @param {SecureRandomGenerator} [generator] - An optional random number generator to reuse.
17
- *
18
- * @description If you require to shuffle multiple times it is adviced to pass the `generator` parameter to avoid creating a new generator for each shuffle. (refer to `createSecureRandomGenerator()` factory)
19
- *
20
- * @returns {Array<T>} The shuffled array.
21
- */
24
+ * Everything this library throws.
25
+ *
26
+ * `message` says what was found and where; `code` is the machine-readable
27
+ * version of the same judgement, and is what a caller should branch on. A
28
+ * failure that came from outside the library — the runtime's Web Crypto, or
29
+ * `JSON.parse` — carries the original in `cause`.
30
+ *
31
+ * @example
32
+ * try {
33
+ * await hmacVerify(secret, body, signature);
34
+ * } catch (error) {
35
+ * if (!(error instanceof UnsecureError)) throw error;
36
+ * switch (error.code) {
37
+ * case "OUT_OF_RANGE": {
38
+ * // The secret failed to load: a deployment problem, not a bad request.
39
+ * return respond(500);
40
+ * }
41
+ * case "PLATFORM": {
42
+ * return respond(503, { cause: error.cause });
43
+ * }
44
+ * default: {
45
+ * return respond(400, { reason: error.code });
46
+ * }
47
+ * }
48
+ * }
49
+ */
50
+ export declare class UnsecureError extends Error {
51
+ readonly code: UnsecureErrorCode;
52
+ constructor(code: UnsecureErrorCode, message: string, options?: ErrorOptions);
53
+ }
22
54
  /**
23
- * Parse JSON while stripping prototype-pollution vectors during parsing.
24
- *
25
- * Uses a reviver to drop own properties named `__proto__`, `prototype`, or
26
- * `constructor` before they can be assigned. For nested payloads this is
27
- * cheaper than parsing first and sanitizing after, and it guarantees no
28
- * unsanitized object ever exists.
29
- *
30
- * @param json The JSON text to parse.
31
- * @returns The parsed value with dangerous keys stripped.
32
- * @throws {SyntaxError} If `json` is not valid JSON.
33
- *
34
- * @example
35
- * const payload = safeJsonParse<{ user: { name: string } }>(untrustedInput);
36
- */
37
- declare function safeJsonParse<T = any>(json: string): T;
55
+ * Generate a Uint8Array of cryptographically secure random bytes. Up to 64
56
+ * bytes come from the shared entropy pool; longer requests go to
57
+ * `crypto.getRandomValues` directly, in 65536-byte chunks.
58
+ *
59
+ * @param length Number of random bytes to generate, from 0 to `2**31 - 1`.
60
+ * @returns A Uint8Array filled with random bytes.
61
+ *
62
+ * @throws {UnsecureError} `OUT_OF_RANGE` if `length` is not an integer in
63
+ * `[0, 2**31 - 1]`.
64
+ *
65
+ * @example
66
+ * const key = secureRandomBytes(32); // 256-bit key material
67
+ */
68
+ export declare function secureRandomBytes(length: number): Uint8Array<ArrayBuffer>;
38
69
  /**
39
- * Remove prototype-pollution vectors from a plain record in-place.
40
- *
41
- * Strips own properties named `__proto__`, `prototype`, and `constructor`
42
- * recursively through nested objects and arrays. Cycle-safe.
43
- *
44
- * Returns the same reference for convenience. Use {@link sanitizeObjectCopy}
45
- * if you need a deep copy with the original preserved.
46
- */
47
- declare function sanitizeObject<T extends Record<string, unknown> | undefined>(obj: T): T;
70
+ * Parse JSON and strip prototype-pollution vectors from the result.
71
+ *
72
+ * `JSON.parse` runs first, then the in-place sanitizer walks the parsed value
73
+ * and removes own properties named `__proto__`, `prototype`, or `constructor`
74
+ * at every depth. Nothing holding a dangerous key survives the call — the
75
+ * sanitizer finishes before the value is returned — and no caller-visible
76
+ * object is ever assigned through, so no prototype is polluted along the way.
77
+ *
78
+ * Any JSON root is handled: objects, arrays, and primitives alike.
79
+ *
80
+ * @param json The JSON text to parse.
81
+ * @returns The parsed value with dangerous keys stripped.
82
+ * @throws {UnsecureError} `MALFORMED` if `json` is not valid JSON — the engine's
83
+ * own error travels as `cause`; `FROZEN` if a dangerous key
84
+ * sits on a frozen or sealed object, see
85
+ * {@link sanitizeObject}.
86
+ *
87
+ * @example
88
+ * const payload = safeJsonParse<{ user: { name: string } }>(untrustedInput);
89
+ */
90
+ export declare function safeJsonParse<T = any>(json: string): T;
48
91
  /**
49
- * Return a sanitized deep copy of `obj`. The input is never mutated.
50
- *
51
- * Dangerous keys (`__proto__`, `prototype`, `constructor`) are stripped
52
- * recursively. The returned structure consists of plain objects (rooted on
53
- * `Object.prototype`) and arrays. Cycle-safe: circular references in the
54
- * input are preserved in the output (pointing at the copied node, not the
55
- * original reference).
56
- *
57
- * Non-object / undefined inputs are returned unchanged.
58
- */
59
- declare function sanitizeObjectCopy<T extends Record<string, unknown> | undefined>(obj: T): T;
92
+ * Remove prototype-pollution vectors from a plain record in-place.
93
+ *
94
+ * Strips own properties named `__proto__`, `prototype`, and `constructor`
95
+ * through nested objects and arrays, enumerable or not. Cycle-safe.
96
+ *
97
+ * Values are read from their property descriptors — array elements included —
98
+ * so a getter is never invoked: an accessor is neither traversed nor removed
99
+ * unless its name is one of the three. A `Proxy` is the exception and cannot
100
+ * be otherwise: its traps run for every property operation, so a proxied
101
+ * object is traversed through its own traps.
102
+ *
103
+ * Traversal reaches every object held in a data property, whatever its
104
+ * prototype. What such an object *holds* internally is another matter: `Map`
105
+ * entries, `Set` members and anything else living outside own properties are
106
+ * never read, so they are never sanitized.
107
+ *
108
+ * Returns the same reference for convenience. Use {@link sanitizeObjectCopy}
109
+ * if you need a deep copy with the original preserved.
110
+ *
111
+ * @throws {UnsecureError} `FROZEN` if a dangerous key cannot be removed because
112
+ * the object holding it is frozen or sealed. Leaving the
113
+ * key in place would report a sanitized object that is not
114
+ * one.
115
+ */
116
+ export declare function sanitizeObject<T extends Record<string, unknown> | undefined>(obj: T): T;
60
117
  /**
61
- * Base64 encoding. Accepts `string` or raw bytes; throws `TypeError` on
62
- * `null`/`undefined`. Empty strings and empty `Uint8Array` return `""`.
63
- */
64
- declare function base64Encode(data: Uint8Array | string): string;
118
+ * Return a sanitized deep copy of `obj`. The input is never mutated.
119
+ *
120
+ * Dangerous keys (`__proto__`, `prototype`, `constructor`) are stripped from
121
+ * every array and plain object reached. A plain object is one rooted on
122
+ * `Object.prototype` or on `null`; copies of both are rooted on
123
+ * `Object.prototype`. Every other value — `Date`, `Map`, `Set`, typed
124
+ * arrays, `RegExp`, class instances, functions — is carried into the copy by
125
+ * reference, exactly as {@link sanitizeObject} leaves it in place. By
126
+ * reference means unchanged *and* unsanitized: what a `Map` or `Set` holds is
127
+ * never read by either function.
128
+ *
129
+ * Only own enumerable data properties are copied — the JSON shape. Accessors
130
+ * are skipped rather than invoked, so the copy never runs caller code; an
131
+ * accessor at an array index leaves a hole there and the elements after it
132
+ * keep their positions. A `Proxy` is traversed through its own traps, which
133
+ * run whatever the copy asks for.
134
+ *
135
+ * Cycle-safe: circular references in the input are preserved in the output
136
+ * (pointing at the copied node, not the original reference).
137
+ *
138
+ * Non-object / undefined inputs — and objects that are not arrays or plain
139
+ * objects — are returned unchanged.
140
+ */
141
+ export declare function sanitizeObjectCopy<T extends Record<string, unknown> | undefined>(obj: T): T;
65
142
  /**
66
- * Base64 URL-safe encoding (no padding). Accepts `string` or raw bytes;
67
- * throws `TypeError` on `null`/`undefined`. Empty inputs return `""`.
68
- */
69
- declare function base64UrlEncode(data: Uint8Array | string): string;
70
- declare function base64Decode<T extends DecodeReturnAs>(data: string | Uint8Array, options: {
71
- returnAs: T;
72
- }): T extends "string" ? string : Uint8Array<ArrayBuffer>;
73
- declare function base64Decode(data: string): string;
74
- declare function base64Decode(data: Uint8Array): Uint8Array<ArrayBuffer>;
75
- declare function base64UrlDecode<T extends DecodeReturnAs>(data: string | Uint8Array, options: {
76
- returnAs: T;
77
- }): T extends "string" ? string : Uint8Array<ArrayBuffer>;
78
- declare function base64UrlDecode(data: string): string;
79
- declare function base64UrlDecode(data: Uint8Array): Uint8Array<ArrayBuffer>;
143
+ * Shared UTF-8 `TextEncoder`. Encoding holds no state between calls, so a
144
+ * single instance serves every caller.
145
+ */
146
+ export declare const textEncoder: TextEncoder;
80
147
  /**
81
- * Hex encoding. Accepts `string` or raw bytes; throws `TypeError` on
82
- * `null`/`undefined`. Empty strings and empty `Uint8Array` return `""`.
83
- */
148
+ * Any byte container the library accepts: an `ArrayBuffer` — shared or not —
149
+ * or a view over one. Wider than the DOM `BufferSource`, which excludes
150
+ * `SharedArrayBuffer`-backed views.
151
+ */
152
+ export type BytesSource = ArrayBufferLike | ArrayBufferView<ArrayBufferLike>;
84
153
  /**
85
- * Output-shape option shared by `hexDecode`, `base64Decode`, `base64UrlDecode`,
86
- * and `base32Decode`. Decoders mirror their input type when this is omitted:
87
- * `string` input decodes to `string`, `Uint8Array` input decodes to `Uint8Array`.
88
- *
89
- * `"bytes"` is an alias for `"uint8array"`.
90
- */
91
- type DecodeReturnAs = "string" | "uint8array" | "bytes";
92
- declare const textEncoder: TextEncoder;
93
- declare const textDecoder: TextDecoder;
94
- export { base64Decode, base64Encode, base64UrlDecode, base64UrlEncode, safeJsonParse, sanitizeObject, sanitizeObjectCopy, secureRandomBytes, textDecoder, textEncoder };
154
+ * Shared UTF-8 `TextDecoder` instance. `ignoreBOM` keeps a leading U+FEFF in
155
+ * the output: what the codecs decode is a byte string, and a BOM inside it is
156
+ * payload, not a signature to swallow.
157
+ */
158
+ export declare const textDecoder: TextDecoder;
159
+ /**
160
+ * Decoder output shape. Omit to mirror the input (`string` in → `string` out,
161
+ * `Uint8Array` in → `Uint8Array` out). `"bytes"` aliases `"uint8array"`.
162
+ */
163
+ export type DecodeReturnAs = "string" | "uint8array" | "bytes";
164
+ /** Shared `parse` options. */
165
+ export interface DecodeOptions {
166
+ /** Output shape. Mirrors the input type when omitted. */
167
+ returnAs?: DecodeReturnAs;
168
+ /**
169
+ * Tolerate malformed input (skip/normalize) instead of throwing.
170
+ * @default false
171
+ */
172
+ loose?: boolean;
173
+ }