lacewing 1.0.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.
- package/CHANGELOG.md +11 -0
- package/LICENSE +9 -0
- package/NOTICE.md +1 -0
- package/README.md +313 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/src/cookbook/access-refresh.js +86 -0
- package/dist/src/cookbook/access-refresh.js.map +1 -0
- package/dist/src/http/bearer.js +44 -0
- package/dist/src/http/bearer.js.map +1 -0
- package/dist/src/http/cookies.js +96 -0
- package/dist/src/http/cookies.js.map +1 -0
- package/dist/src/jwks/local.js +85 -0
- package/dist/src/jwks/local.js.map +1 -0
- package/dist/src/jwks/remote.js +121 -0
- package/dist/src/jwks/remote.js.map +1 -0
- package/dist/src/jwt/decrypt.js +126 -0
- package/dist/src/jwt/decrypt.js.map +1 -0
- package/dist/src/jwt/decryption_profile.js +78 -0
- package/dist/src/jwt/decryption_profile.js.map +1 -0
- package/dist/src/jwt/encrypt.js +149 -0
- package/dist/src/jwt/encrypt.js.map +1 -0
- package/dist/src/jwt/profile.js +102 -0
- package/dist/src/jwt/profile.js.map +1 -0
- package/dist/src/jwt/sign.js +173 -0
- package/dist/src/jwt/sign.js.map +1 -0
- package/dist/src/jwt/verify.js +118 -0
- package/dist/src/jwt/verify.js.map +1 -0
- package/dist/src/key/encryption.js +132 -0
- package/dist/src/key/encryption.js.map +1 -0
- package/dist/src/key/export.js +46 -0
- package/dist/src/key/export.js.map +1 -0
- package/dist/src/key/generate.js +47 -0
- package/dist/src/key/generate.js.map +1 -0
- package/dist/src/key/import.js +136 -0
- package/dist/src/key/import.js.map +1 -0
- package/dist/src/legacy/rs256.js +11 -0
- package/dist/src/legacy/rs256.js.map +1 -0
- package/dist/src/legacy/rsa.js +37 -0
- package/dist/src/legacy/rsa.js.map +1 -0
- package/dist/src/lib/algorithms.js +60 -0
- package/dist/src/lib/algorithms.js.map +1 -0
- package/dist/src/lib/base64url.js +28 -0
- package/dist/src/lib/base64url.js.map +1 -0
- package/dist/src/lib/claims.js +111 -0
- package/dist/src/lib/claims.js.map +1 -0
- package/dist/src/lib/duration.js +24 -0
- package/dist/src/lib/duration.js.map +1 -0
- package/dist/src/lib/entropy.js +70 -0
- package/dist/src/lib/entropy.js.map +1 -0
- package/dist/src/lib/headers.js +75 -0
- package/dist/src/lib/headers.js.map +1 -0
- package/dist/src/lib/invariants.js +12 -0
- package/dist/src/lib/invariants.js.map +1 -0
- package/dist/src/lib/json.js +140 -0
- package/dist/src/lib/json.js.map +1 -0
- package/dist/src/lib/jwe_algorithms.js +81 -0
- package/dist/src/lib/jwe_algorithms.js.map +1 -0
- package/dist/src/lib/payload_hygiene.js +116 -0
- package/dist/src/lib/payload_hygiene.js.map +1 -0
- package/dist/src/lib/utf8.js +27 -0
- package/dist/src/lib/utf8.js.map +1 -0
- package/dist/src/revocation/memory.js +67 -0
- package/dist/src/revocation/memory.js.map +1 -0
- package/dist/src/revocation/store.js +25 -0
- package/dist/src/revocation/store.js.map +1 -0
- package/dist/src/types.js +51 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/util/errors.js +96 -0
- package/dist/src/util/errors.js.map +1 -0
- package/dist/src/util/unsafe-decode.js +45 -0
- package/dist/src/util/unsafe-decode.js.map +1 -0
- package/dist/types/index.d.ts +29 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/src/cookbook/access-refresh.d.ts +77 -0
- package/dist/types/src/cookbook/access-refresh.d.ts.map +1 -0
- package/dist/types/src/http/bearer.d.ts +20 -0
- package/dist/types/src/http/bearer.d.ts.map +1 -0
- package/dist/types/src/http/cookies.d.ts +38 -0
- package/dist/types/src/http/cookies.d.ts.map +1 -0
- package/dist/types/src/jwks/local.d.ts +16 -0
- package/dist/types/src/jwks/local.d.ts.map +1 -0
- package/dist/types/src/jwks/remote.d.ts +23 -0
- package/dist/types/src/jwks/remote.d.ts.map +1 -0
- package/dist/types/src/jwt/decrypt.d.ts +23 -0
- package/dist/types/src/jwt/decrypt.d.ts.map +1 -0
- package/dist/types/src/jwt/decryption_profile.d.ts +32 -0
- package/dist/types/src/jwt/decryption_profile.d.ts.map +1 -0
- package/dist/types/src/jwt/encrypt.d.ts +34 -0
- package/dist/types/src/jwt/encrypt.d.ts.map +1 -0
- package/dist/types/src/jwt/profile.d.ts +37 -0
- package/dist/types/src/jwt/profile.d.ts.map +1 -0
- package/dist/types/src/jwt/sign.d.ts +59 -0
- package/dist/types/src/jwt/sign.d.ts.map +1 -0
- package/dist/types/src/jwt/verify.d.ts +41 -0
- package/dist/types/src/jwt/verify.d.ts.map +1 -0
- package/dist/types/src/key/encryption.d.ts +37 -0
- package/dist/types/src/key/encryption.d.ts.map +1 -0
- package/dist/types/src/key/export.d.ts +10 -0
- package/dist/types/src/key/export.d.ts.map +1 -0
- package/dist/types/src/key/generate.d.ts +27 -0
- package/dist/types/src/key/generate.d.ts.map +1 -0
- package/dist/types/src/key/import.d.ts +20 -0
- package/dist/types/src/key/import.d.ts.map +1 -0
- package/dist/types/src/legacy/rs256.d.ts +11 -0
- package/dist/types/src/legacy/rs256.d.ts.map +1 -0
- package/dist/types/src/legacy/rsa.d.ts +25 -0
- package/dist/types/src/legacy/rsa.d.ts.map +1 -0
- package/dist/types/src/lib/algorithms.d.ts +34 -0
- package/dist/types/src/lib/algorithms.d.ts.map +1 -0
- package/dist/types/src/lib/base64url.d.ts +8 -0
- package/dist/types/src/lib/base64url.d.ts.map +1 -0
- package/dist/types/src/lib/claims.d.ts +15 -0
- package/dist/types/src/lib/claims.d.ts.map +1 -0
- package/dist/types/src/lib/duration.d.ts +7 -0
- package/dist/types/src/lib/duration.d.ts.map +1 -0
- package/dist/types/src/lib/entropy.d.ts +21 -0
- package/dist/types/src/lib/entropy.d.ts.map +1 -0
- package/dist/types/src/lib/headers.d.ts +19 -0
- package/dist/types/src/lib/headers.d.ts.map +1 -0
- package/dist/types/src/lib/invariants.d.ts +6 -0
- package/dist/types/src/lib/invariants.d.ts.map +1 -0
- package/dist/types/src/lib/json.d.ts +24 -0
- package/dist/types/src/lib/json.d.ts.map +1 -0
- package/dist/types/src/lib/jwe_algorithms.d.ts +46 -0
- package/dist/types/src/lib/jwe_algorithms.d.ts.map +1 -0
- package/dist/types/src/lib/payload_hygiene.d.ts +20 -0
- package/dist/types/src/lib/payload_hygiene.d.ts.map +1 -0
- package/dist/types/src/lib/utf8.d.ts +7 -0
- package/dist/types/src/lib/utf8.d.ts.map +1 -0
- package/dist/types/src/revocation/memory.d.ts +22 -0
- package/dist/types/src/revocation/memory.d.ts.map +1 -0
- package/dist/types/src/revocation/store.d.ts +17 -0
- package/dist/types/src/revocation/store.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +196 -0
- package/dist/types/src/types.d.ts.map +1 -0
- package/dist/types/src/util/errors.d.ts +89 -0
- package/dist/types/src/util/errors.d.ts.map +1 -0
- package/dist/types/src/util/unsafe-decode.d.ts +21 -0
- package/dist/types/src/util/unsafe-decode.d.ts.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one and only verification path (RFC 8725 §3.3).
|
|
3
|
+
*
|
|
4
|
+
* Order of operations, fail-fast, all-or-nothing:
|
|
5
|
+
* 1. structural parse (length cap, strict base64url, strict UTF-8)
|
|
6
|
+
* 2. header validation (allowlist, typ, kid hygiene, forbidden params)
|
|
7
|
+
* 3. key resolution from the profile's key source
|
|
8
|
+
* 4. signature verification
|
|
9
|
+
* 5. claims validation
|
|
10
|
+
* 6. custom claim validators
|
|
11
|
+
* 7. revocation check - last, so unauthenticated input can never
|
|
12
|
+
* drive store lookups (LW-rev.3)
|
|
13
|
+
*
|
|
14
|
+
* There is no partial result and no decoded-but-unverified escape hatch
|
|
15
|
+
* here; that lives, loudly branded, in `util/unsafe-decode.ts`.
|
|
16
|
+
*/
|
|
17
|
+
import { type ExpectedJwtProfile, type VerifiedJwt } from "../types.js";
|
|
18
|
+
/**
|
|
19
|
+
* Verify a token against a profile. The returned {@link VerifiedJwt} is
|
|
20
|
+
* the only way to obtain one - there is no backdoor.
|
|
21
|
+
*
|
|
22
|
+
* On any failure it throws a typed error ({@link JWTExpired},
|
|
23
|
+
* {@link AlgorithmNotAllowed}, {@link JWTClaimValidationFailed}, ...) and yields
|
|
24
|
+
* no partial result. There is no `decode()` and no `ignoreExpiration`.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const profile = defineProfile({
|
|
29
|
+
* typ: "at+jwt",
|
|
30
|
+
* issuer: "https://auth.example.com",
|
|
31
|
+
* audience: "https://api.example.com",
|
|
32
|
+
* algorithms: ["EdDSA"],
|
|
33
|
+
* keys: createRemoteJWKSet("https://auth.example.com/jwks"),
|
|
34
|
+
* maxTokenAge: "10m",
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* const { payload } = await jwtVerify(token, profile); // every check passed
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function jwtVerify(token: string, profile: ExpectedJwtProfile): Promise<VerifiedJwt>;
|
|
41
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../../src/jwt/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAgBH,OAAO,EAEN,KAAK,kBAAkB,EAIvB,KAAK,WAAW,EAChB,MAAM,aAAa,CAAC;AAwBrB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,SAAS,CAC9B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,kBAAkB,GACzB,OAAO,CAAC,WAAW,CAAC,CA+DtB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encryption key import/generation (the JWE counterpart of `key/import.ts` and
|
|
3
|
+
* `key/generate.ts`). Every encryption key enters here and leaves bound to
|
|
4
|
+
* exactly one key-management algorithm, carried in the type. `EncryptJWT` and
|
|
5
|
+
* `jwtDecrypt` never accept a bare `CryptoKey`, so the binding cannot be
|
|
6
|
+
* bypassed - and a signing key can never be used to encrypt (different brand).
|
|
7
|
+
*/
|
|
8
|
+
import { type LacewingEncryptionKey, type StaticJWK } from "../types.js";
|
|
9
|
+
/** JWK object, PEM string (PKCS#8 / SPKI), raw secret, or a CryptoKey. */
|
|
10
|
+
export type EncryptionKeyMaterial = StaticJWK | string | Uint8Array | CryptoKey;
|
|
11
|
+
export interface GenerateEncryptionKeyPairOptions {
|
|
12
|
+
extractable?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Generate an asymmetric encryption key pair for `algorithm` (ECDH-ES* or
|
|
16
|
+
* RSA-OAEP-256). The recipient keeps the private key; senders encrypt to the
|
|
17
|
+
* public key.
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateEncryptionKeyPair<const Alg extends string>(algorithm: Alg, options?: GenerateEncryptionKeyPairOptions): Promise<{
|
|
20
|
+
publicKey: LacewingEncryptionKey<Alg>;
|
|
21
|
+
privateKey: LacewingEncryptionKey<Alg>;
|
|
22
|
+
}>;
|
|
23
|
+
/** Generate a random symmetric key for an AES key-wrapping algorithm (A*KW / A*GCMKW). */
|
|
24
|
+
export declare function generateEncryptionSecret<const Alg extends string>(algorithm: Alg): LacewingEncryptionKey<Alg>;
|
|
25
|
+
/**
|
|
26
|
+
* Generate a random direct (`alg: "dir"`) key sized to a content-encryption
|
|
27
|
+
* algorithm. The key *is* the content-encryption key, so it is inseparable
|
|
28
|
+
* from its `enc`: a 32-byte key is for A256GCM/A128CBC-HS256, and so on.
|
|
29
|
+
*/
|
|
30
|
+
export declare function generateDirectKey<const Enc extends string>(enc: Enc): LacewingEncryptionKey<"dir">;
|
|
31
|
+
/**
|
|
32
|
+
* Import encryption key material and bind it to `algorithm`. Throws
|
|
33
|
+
* {@link KeyTypeMismatch} when material and algorithm disagree, and
|
|
34
|
+
* {@link KeyImportFailed} for anything else.
|
|
35
|
+
*/
|
|
36
|
+
export declare function importEncryptionKey<const Alg extends string>(material: EncryptionKeyMaterial, algorithm: Alg): Promise<LacewingEncryptionKey<Alg>>;
|
|
37
|
+
//# sourceMappingURL=encryption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../../../src/key/encryption.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EAGN,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACd,MAAM,aAAa,CAAC;AAErB,0EAA0E;AAC1E,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAEhF,MAAM,WAAW,gCAAgC;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAWD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,KAAK,CAAC,GAAG,SAAS,MAAM,EACvE,SAAS,EAAE,GAAG,EACd,OAAO,GAAE,gCAAqC,GAC5C,OAAO,CAAC;IAAE,SAAS,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAAC,UAAU,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;CAAE,CAAC,CAiB5F;AAED,0FAA0F;AAC1F,wBAAgB,wBAAwB,CAAC,KAAK,CAAC,GAAG,SAAS,MAAM,EAChE,SAAS,EAAE,GAAG,GACZ,qBAAqB,CAAC,GAAG,CAAC,CAO5B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,GAAG,SAAS,MAAM,EACzD,GAAG,EAAE,GAAG,GACN,qBAAqB,CAAC,KAAK,CAAC,CAM9B;AAsDD;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,CAAC,GAAG,SAAS,MAAM,EACjE,QAAQ,EAAE,qBAAqB,EAC/B,SAAS,EAAE,GAAG,GACZ,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAarC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key export to JWK / PEM. Only works on extractable keys - keys from
|
|
3
|
+
* `generateKeyPair` are non-extractable unless you asked otherwise.
|
|
4
|
+
*/
|
|
5
|
+
import type { LacewingKey, StaticJWK } from "../types.js";
|
|
6
|
+
/** Export a key as a JWK, with its bound `alg` and `use: "sig"` set. */
|
|
7
|
+
export declare function exportKeyJWK(key: LacewingKey): Promise<StaticJWK>;
|
|
8
|
+
/** Export an asymmetric key as PEM (PKCS#8 for private, SPKI for public). */
|
|
9
|
+
export declare function exportKeyPEM(key: LacewingKey): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../../src/key/export.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE1D,wEAAwE;AACxE,wBAAsB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAkBvE;AAED,6EAA6E;AAC7E,wBAAsB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAapE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key generation with safe defaults:
|
|
3
|
+
* asymmetric-first - EdDSA unless you say otherwise - and secrets that
|
|
4
|
+
* are always cryptographically random at the algorithm's minimum size.
|
|
5
|
+
*/
|
|
6
|
+
import { type LacewingKey } from "../types.js";
|
|
7
|
+
export interface GenerateKeyPairOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Whether the private key may be exported later (default false -
|
|
10
|
+
* non-extractable keys can't leak through `exportKey*`).
|
|
11
|
+
*/
|
|
12
|
+
extractable?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Generate an asymmetric key pair, bound to `algorithm` (default EdDSA).
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateKeyPair<const Alg extends string = "EdDSA">(algorithm?: Alg, options?: GenerateKeyPairOptions): Promise<{
|
|
18
|
+
publicKey: LacewingKey<Alg>;
|
|
19
|
+
privateKey: LacewingKey<Alg>;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Generate a random HMAC secret at the algorithm's minimum size
|
|
23
|
+
* (default HS256 -> 256 bits). Always passes the entropy checks by
|
|
24
|
+
* construction.
|
|
25
|
+
*/
|
|
26
|
+
export declare function generateSecret<const Alg extends string = "HS256">(algorithm?: Alg): LacewingKey<Alg>;
|
|
27
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../../src/key/generate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAA6B,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1E,MAAM,WAAW,sBAAsB;IACtC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,KAAK,CAAC,GAAG,SAAS,MAAM,GAAG,OAAO,EACvE,SAAS,GAAE,GAAoB,EAC/B,OAAO,GAAE,sBAA2B,GAClC,OAAO,CAAC;IAAE,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAAC,UAAU,EAAE,WAAW,CAAC,GAAG,CAAC,CAAA;CAAE,CAAC,CAmBxE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,GAAG,SAAS,MAAM,GAAG,OAAO,EAChE,SAAS,GAAE,GAAoB,GAC7B,WAAW,CAAC,GAAG,CAAC,CAWlB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key import with algorithm binding (RFC 8725 §3.1/§3.2/§3.5).
|
|
3
|
+
*
|
|
4
|
+
* Every key enters Lacewing through this module and leaves bound to
|
|
5
|
+
* exactly one algorithm, carried in the type system. Sign/verify never
|
|
6
|
+
* accept raw `CryptoKey`s, so the alg-to-key binding cannot be bypassed.
|
|
7
|
+
*/
|
|
8
|
+
import { type LacewingKey, type StaticJWK } from "../types.js";
|
|
9
|
+
/** JWK object, PEM string (PKCS#8 / SPKI), raw secret, or a CryptoKey. */
|
|
10
|
+
export type KeyMaterial = StaticJWK | string | Uint8Array | CryptoKey;
|
|
11
|
+
/**
|
|
12
|
+
* Import key material and bind it to `algorithm`. The returned
|
|
13
|
+
* {@link LacewingKey} can only ever be used with that algorithm.
|
|
14
|
+
*
|
|
15
|
+
* Throws {@link KeyTypeMismatch} when material and algorithm disagree,
|
|
16
|
+
* {@link EntropyCheckFailed} for weak HMAC secrets, and
|
|
17
|
+
* {@link KeyImportFailed} for anything else that goes wrong.
|
|
18
|
+
*/
|
|
19
|
+
export declare function importKey<const Alg extends string>(material: KeyMaterial, algorithm: Alg): Promise<LacewingKey<Alg>>;
|
|
20
|
+
//# sourceMappingURL=import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../../src/key/import.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,OAAO,EAGN,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,MAAM,aAAa,CAAC;AAErB,0EAA0E;AAC1E,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAuHtE;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,KAAK,CAAC,GAAG,SAAS,MAAM,EACvD,QAAQ,EAAE,WAAW,EACrB,SAAS,EAAE,GAAG,GACZ,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAoB3B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LEGACY INTEROP - explicit opt-in only.
|
|
3
|
+
*
|
|
4
|
+
* `RS256` (RSASSA-PKCS1-v1_5) is not in Lacewing's default registry. This
|
|
5
|
+
* module is kept for backwards compatibility and re-exports the RS256 opt-in
|
|
6
|
+
* from {@link module:legacy/rsa}, where the rest of the `RS*` family lives.
|
|
7
|
+
* Calling {@link enableLegacyRS256} is the grep-loud marker code review looks
|
|
8
|
+
* for; prefer `PS256`/`EdDSA` everywhere you control both sides.
|
|
9
|
+
*/
|
|
10
|
+
export { enableLegacyRS256 } from "./rsa.js";
|
|
11
|
+
//# sourceMappingURL=rs256.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rs256.d.ts","sourceRoot":"","sources":["../../../../src/legacy/rs256.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LEGACY INTEROP - explicit opt-in only.
|
|
3
|
+
*
|
|
4
|
+
* The `RS*` family (RSASSA-PKCS1-v1_5) is not in Lacewing's default registry:
|
|
5
|
+
* PKCS#1 v1.5 signatures are the deprecated ancestor of RSA-PSS and only
|
|
6
|
+
* belong in systems that must interoperate with issuers that cannot emit
|
|
7
|
+
* `PS256`/`EdDSA`. Each `enable...` call is the grep-loud marker code review
|
|
8
|
+
* looks for; prefer `PS256`/`EdDSA` everywhere you control both sides.
|
|
9
|
+
*
|
|
10
|
+
* `none` can never enter through this door - `registerLegacyAlgorithm` refuses
|
|
11
|
+
* it - and neither can any algorithm not on this curated legacy list.
|
|
12
|
+
*/
|
|
13
|
+
/** Register legacy `RS256`. After this, importKey/profiles/JWKS accept it. */
|
|
14
|
+
export declare function enableLegacyRS256(): void;
|
|
15
|
+
/** Register legacy `RS384`. Prefer `PS384`/`EdDSA` where you control both sides. */
|
|
16
|
+
export declare function enableLegacyRS384(): void;
|
|
17
|
+
/** Register legacy `RS512`. Prefer `PS512`/`EdDSA` where you control both sides. */
|
|
18
|
+
export declare function enableLegacyRS512(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Register the whole legacy `RS256`/`RS384`/`RS512` family at once, for
|
|
21
|
+
* interop with an issuer that may rotate across hash sizes. Still an explicit,
|
|
22
|
+
* grep-loud opt-in - do not call it "just in case".
|
|
23
|
+
*/
|
|
24
|
+
export declare function enableLegacyRSA(): void;
|
|
25
|
+
//# sourceMappingURL=rsa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rsa.d.ts","sourceRoot":"","sources":["../../../../src/legacy/rsa.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,8EAA8E;AAC9E,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAItC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The algorithm registry - single source of truth for which algorithms
|
|
3
|
+
* exist and which key types they pair with (RFC 8725 §3.1/§3.2).
|
|
4
|
+
*
|
|
5
|
+
* `none`, `RSA1_5` and `RS*` are simply absent. Adding an algorithm is a
|
|
6
|
+
* one-entry change here (cryptographic agility, §3.2.4). Legacy interop
|
|
7
|
+
* algorithms can only enter through `registerLegacyAlgorithm`, which is
|
|
8
|
+
* reachable exclusively via the explicit `legacy/` imports.
|
|
9
|
+
*/
|
|
10
|
+
import { type ValidAlg } from "../types.js";
|
|
11
|
+
export interface AlgorithmInfo {
|
|
12
|
+
/** JOSE algorithm identifier, e.g. "EdDSA". */
|
|
13
|
+
readonly name: string;
|
|
14
|
+
/** JWK key type this algorithm pairs with. */
|
|
15
|
+
readonly kty: "OKP" | "EC" | "RSA" | "oct";
|
|
16
|
+
/** Named curve for EC/OKP algorithms. */
|
|
17
|
+
readonly crv?: string;
|
|
18
|
+
/** Minimum key size in bits (secret length for `oct`, modulus for RSA). */
|
|
19
|
+
readonly minKeyBits: number;
|
|
20
|
+
}
|
|
21
|
+
/** Type guard: is this exact string an allowed algorithm? Case sensitive. */
|
|
22
|
+
export declare function isValidAlgorithm(alg: string): boolean;
|
|
23
|
+
/** Look up an algorithm's properties, or throw {@link AlgorithmNotAllowed}. */
|
|
24
|
+
export declare function getAlgorithmProperties(alg: string): AlgorithmInfo;
|
|
25
|
+
/** Validate against the registry and brand the string as {@link ValidAlg}. */
|
|
26
|
+
export declare function toValidAlg(alg: string): ValidAlg;
|
|
27
|
+
/** Currently registered algorithm names (core + any enabled legacy). */
|
|
28
|
+
export declare function listAlgorithms(): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Internal - only the `legacy/` modules call this. Registers an interop
|
|
31
|
+
* algorithm so it becomes importable/verifiable. Never accepts `none`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function registerLegacyAlgorithm(info: AlgorithmInfo): void;
|
|
34
|
+
//# sourceMappingURL=algorithms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"algorithms.d.ts","sourceRoot":"","sources":["../../../../src/lib/algorithms.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,QAAQ,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;IAC3C,yCAAyC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAoBD,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,+EAA+E;AAC/E,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAOjE;AAED,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAGhD;AAED,wEAAwE;AACxE,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAEzC;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAOjE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict base64url (RFC 7515 §2: no padding, no whitespace, no URL-unsafe
|
|
3
|
+
* characters). Non-canonical encodings are rejected to close parser
|
|
4
|
+
* differentials between Lacewing and other JWT consumers.
|
|
5
|
+
*/
|
|
6
|
+
export declare function encodeBase64url(bytes: Uint8Array): string;
|
|
7
|
+
export declare function decodeBase64url(encoded: string): Uint8Array;
|
|
8
|
+
//# sourceMappingURL=base64url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64url.d.ts","sourceRoot":"","sources":["../../../../src/lib/base64url.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEzD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAe3D"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claims validation engine (RFC 8725 §3.8/§3.9).
|
|
3
|
+
*
|
|
4
|
+
* One pass, fail-fast, all-or-nothing. Rejection messages never echo
|
|
5
|
+
* untrusted token content (log-injection hygiene, §3.10) - errors name
|
|
6
|
+
* the claim, not its value.
|
|
7
|
+
*/
|
|
8
|
+
import type { ClaimsPolicy } from "../types.js";
|
|
9
|
+
export type { ValidateClaim } from "../types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Validate a decoded payload against a profile. Only called after the
|
|
12
|
+
* signature has been verified. `nowSeconds` is injectable for tests.
|
|
13
|
+
*/
|
|
14
|
+
export declare function validateClaims(payload: Record<string, unknown>, profile: ClaimsPolicy, nowSeconds?: number): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=claims.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claims.d.ts","sourceRoot":"","sources":["../../../../src/lib/claims.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAuChD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;GAGG;AACH,wBAAsB,cAAc,CACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,YAAY,EACrB,UAAU,GAAE,MAAsC,GAChD,OAAO,CAAC,IAAI,CAAC,CA4Ef"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-friendly duration parsing: public APIs accept `900` (seconds) or
|
|
3
|
+
* `"15m"`; everything internal works in branded {@link DurationSeconds}.
|
|
4
|
+
*/
|
|
5
|
+
import { type DurationSeconds } from "../types.js";
|
|
6
|
+
export declare function parseDuration(value: number | string): DurationSeconds;
|
|
7
|
+
//# sourceMappingURL=duration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../../../src/lib/duration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAW9D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,CAYrE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HMAC secret strength checks (RFC 8725 §3.5).
|
|
3
|
+
*
|
|
4
|
+
* Two gates at import time:
|
|
5
|
+
* 1. Minimum length per algorithm (RFC 7518: >= hash output size).
|
|
6
|
+
* 2. A heuristic that rejects password-looking strings - the classic
|
|
7
|
+
* `secret: "my-secret"` misuse - even when they are long enough.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Heuristic: does this byte sequence look like a human-chosen password
|
|
11
|
+
* rather than a random key? Only printable-ASCII inputs are suspected -
|
|
12
|
+
* raw random bytes virtually never stay inside that range.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isPasswordLike(bytes: Uint8Array): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Validate an HMAC secret for the given HS* algorithm.
|
|
17
|
+
* Throws {@link EntropyCheckFailed} when the secret is too short or
|
|
18
|
+
* looks like a password.
|
|
19
|
+
*/
|
|
20
|
+
export declare function validateHMACSecret(secret: Uint8Array, algorithmName: string): void;
|
|
21
|
+
//# sourceMappingURL=entropy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entropy.d.ts","sourceRoot":"","sources":["../../../../src/lib/entropy.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA+BH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAYzD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAelF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Header parsing and hardening (RFC 8725 §3.1/§3.2/§3.6/§3.10/§3.11).
|
|
3
|
+
*
|
|
4
|
+
* Header values are untrusted input: `kid` is length-capped and
|
|
5
|
+
* character-whitelisted before any lookup, `jku`/`x5u`/`jwk`/`x5c` are
|
|
6
|
+
* never honored, `zip` is rejected outright, and `crit` is rejected
|
|
7
|
+
* because Lacewing supports no header extensions.
|
|
8
|
+
*/
|
|
9
|
+
import { type ExpectedJwtProfile, type JwtHeader } from "../types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Sanitize an untrusted `kid` before it is used for key lookup (§3.10):
|
|
12
|
+
* bounded length, conservative charset.
|
|
13
|
+
*/
|
|
14
|
+
export declare function sanitizeKid(kid: unknown): string;
|
|
15
|
+
/** Compare `typ` values per RFC 9068: optional media-type prefix, case-insensitive. */
|
|
16
|
+
export declare function normalizeTyp(typ: string): string;
|
|
17
|
+
/** Validate a decoded (but unverified) header object against a profile. */
|
|
18
|
+
export declare function validateHeader(raw: unknown, profile: ExpectedJwtProfile): JwtHeader;
|
|
19
|
+
//# sourceMappingURL=headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../../../src/lib/headers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAU,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAS9E;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAUhD;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,GAAG,SAAS,CA0CnF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Internal assertion helpers. */
|
|
2
|
+
/** Throw if `condition` is false. For states that must be impossible. */
|
|
3
|
+
export declare function invariant(condition: unknown, message: string): asserts condition;
|
|
4
|
+
/** Exhaustiveness check for switch statements. */
|
|
5
|
+
export declare function assertNever(value: never): never;
|
|
6
|
+
//# sourceMappingURL=invariants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invariants.d.ts","sourceRoot":"","sources":["../../../../src/lib/invariants.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAElC,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAIhF;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict JSON object parsing for token segments (RFC 8725 §3.7 strictness).
|
|
3
|
+
*
|
|
4
|
+
* `JSON.parse` silently keeps the *last* value when a member name is
|
|
5
|
+
* duplicated. That is a parser differential: an attacker crafts a header or
|
|
6
|
+
* payload where Lacewing and another consumer disagree about, say, which
|
|
7
|
+
* `alg` or `aud` is authoritative. RFC 8259 §4 says names SHOULD be unique
|
|
8
|
+
* and that behavior is otherwise unpredictable - Lacewing treats a duplicate
|
|
9
|
+
* key at any nesting level as malformed and rejects the token.
|
|
10
|
+
*
|
|
11
|
+
* The scan runs only after `JSON.parse` has confirmed the text is
|
|
12
|
+
* well-formed, so it can assume valid JSON and stay small.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Throw {@link JWTInvalid} if `text` (already known to be valid JSON) contains
|
|
16
|
+
* a duplicated member name in any object at any depth.
|
|
17
|
+
*/
|
|
18
|
+
export declare function assertNoDuplicateKeys(text: string, what: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Decode a token segment's UTF-8 text into a JSON object, rejecting anything
|
|
21
|
+
* that is not a plain object and any duplicate member names.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseJsonObject(text: string, what: string): Record<string, unknown>;
|
|
24
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../../../src/lib/json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAiEH;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CA8CtE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAanF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The JWE algorithm registry (encrypted JWTs). Two axes, both curated:
|
|
3
|
+
*
|
|
4
|
+
* - key management (`alg`): how the content-encryption key is agreed/wrapped.
|
|
5
|
+
* - content encryption (`enc`): the AEAD that actually encrypts the payload.
|
|
6
|
+
*
|
|
7
|
+
* Deliberately absent, exactly as on the JWS side: `none`, `RSA1_5`
|
|
8
|
+
* (Bleichenbacher - CVE-2023-... class), `RSA-OAEP` with SHA-1, and the `PBES2*`
|
|
9
|
+
* password-based algorithms (Lacewing does not do human-memorable secrets).
|
|
10
|
+
* As with JWS, the token header never chooses - the decryption profile does.
|
|
11
|
+
*
|
|
12
|
+
* Portability note: the `A192*` entries work on Node >= 24 (the engine floor)
|
|
13
|
+
* but 192-bit AES is not implemented by browser WebCrypto and some edge
|
|
14
|
+
* runtimes. Documented in the README; prefer `A128*`/`A256*` for tokens that
|
|
15
|
+
* must be decrypted outside Node.
|
|
16
|
+
*/
|
|
17
|
+
import { type ValidAlg } from "../types.js";
|
|
18
|
+
export interface JweKeyManagementInfo {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/** Family: direct key, AES key-wrap, ECDH-ES (opt. wrap), or RSA-OAEP-256. */
|
|
21
|
+
readonly kind: "dir" | "aeskw" | "ecdh" | "rsa";
|
|
22
|
+
/** JWK key type the recipient key must have. */
|
|
23
|
+
readonly kty: "EC" | "RSA" | "oct";
|
|
24
|
+
/** Symmetric secret size in bytes (aeskw only). */
|
|
25
|
+
readonly secretBytes?: number;
|
|
26
|
+
/** Minimum RSA modulus in bits (rsa only). */
|
|
27
|
+
readonly minKeyBits?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface JweContentEncryptionInfo {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
/** Content-encryption key size in bytes - the size a `dir` key must be. */
|
|
32
|
+
readonly cekBytes: number;
|
|
33
|
+
}
|
|
34
|
+
export declare function isValidKeyManagementAlgorithm(alg: string): boolean;
|
|
35
|
+
export declare function isValidContentEncryptionAlgorithm(enc: string): boolean;
|
|
36
|
+
/** Look up a key-management algorithm, or throw {@link AlgorithmNotAllowed}. */
|
|
37
|
+
export declare function getKeyManagementProperties(alg: string): JweKeyManagementInfo;
|
|
38
|
+
/** Look up a content-encryption algorithm, or throw {@link AlgorithmNotAllowed}. */
|
|
39
|
+
export declare function getContentEncryptionProperties(enc: string): JweContentEncryptionInfo;
|
|
40
|
+
/** Validate against the registry and brand the key-management alg. */
|
|
41
|
+
export declare function toValidKeyManagementAlg(alg: string): ValidAlg;
|
|
42
|
+
/** Validate against the registry and brand the content-encryption alg. */
|
|
43
|
+
export declare function toValidContentEncryptionAlg(enc: string): ValidAlg;
|
|
44
|
+
export declare function listKeyManagementAlgorithms(): string[];
|
|
45
|
+
export declare function listContentEncryptionAlgorithms(): string[];
|
|
46
|
+
//# sourceMappingURL=jwe_algorithms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwe_algorithms.d.ts","sourceRoot":"","sources":["../../../../src/lib/jwe_algorithms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;IAChD,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;IACnC,mDAAmD;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AA6BD,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAElE;AAED,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED,gFAAgF;AAChF,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAM5E;AAED,oFAAoF;AACpF,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,MAAM,GAAG,wBAAwB,CAMpF;AAED,sEAAsE;AACtE,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAG7D;AAED,0EAA0E;AAC1E,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAGjE;AAED,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD;AAED,wBAAgB,+BAA+B,IAAI,MAAM,EAAE,CAE1D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sign-time payload hygiene scanner (LW-payload).
|
|
3
|
+
*
|
|
4
|
+
* JWS payloads are base64url-encoded **plaintext** - encoding, not
|
|
5
|
+
* encryption. Two tiers, applied recursively so nesting offers no blind
|
|
6
|
+
* spots:
|
|
7
|
+
* - claim *names* matching a deny-heuristic (`password`, `secret`, ...)
|
|
8
|
+
* - claim *values* matching high-confidence secret patterns (Luhn-valid
|
|
9
|
+
* card numbers, PEM private-key blocks, other JWTs)
|
|
10
|
+
*
|
|
11
|
+
* False positives are waived per top-level claim via the grep-loud
|
|
12
|
+
* `SignJWT.unsafeAllowClaim(name)`.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Scan a payload about to be signed. Throws {@link PayloadHygieneViolation}
|
|
16
|
+
* naming the offending claim (never echoing its value). Claims listed in
|
|
17
|
+
* `allowedClaims` are skipped entirely, subtree included.
|
|
18
|
+
*/
|
|
19
|
+
export declare function scanPayloadForSensitiveData(payload: Record<string, unknown>, allowedClaims?: ReadonlySet<string>): void;
|
|
20
|
+
//# sourceMappingURL=payload_hygiene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload_hygiene.d.ts","sourceRoot":"","sources":["../../../../src/lib/payload_hygiene.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAwGH;;;;GAIG;AACH,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,aAAa,GAAE,WAAW,CAAC,MAAM,CAAa,GAC5C,IAAI,CAgBN"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict UTF-8 encode/decode (RFC 8725 §3.7). Malformed sequences reject
|
|
3
|
+
* the token - no replacement characters, no silently stripped BOM.
|
|
4
|
+
*/
|
|
5
|
+
export declare function encodeUTF8(text: string): Uint8Array;
|
|
6
|
+
export declare function decodeUTF8(bytes: Uint8Array): string;
|
|
7
|
+
//# sourceMappingURL=utf8.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utf8.d.ts","sourceRoot":"","sources":["../../../../src/lib/utf8.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAKnD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAMpD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory {@link RevocationStore}.
|
|
3
|
+
*
|
|
4
|
+
* Entries evict once the revoked token's `exp` passes: a revocation only
|
|
5
|
+
* needs to outlive the token it revokes. Suitable for single-process
|
|
6
|
+
* deployments and tests; multi-instance services want a shared backend
|
|
7
|
+
* (Redis/DB) implementing the same interface.
|
|
8
|
+
*/
|
|
9
|
+
import type { RevocationStore, TokenRevocationContext } from "../types.js";
|
|
10
|
+
export declare class MemoryRevocationStore implements RevocationStore {
|
|
11
|
+
#private;
|
|
12
|
+
/**
|
|
13
|
+
* Revoke a token by its `jti`. `expiresAt` is the token's `exp`
|
|
14
|
+
* (unix seconds or Date) - the entry is dropped after that moment.
|
|
15
|
+
*/
|
|
16
|
+
revoke(jti: string, expiresAt: number | Date): void;
|
|
17
|
+
isRevoked(context: TokenRevocationContext): Promise<boolean>;
|
|
18
|
+
isAnyRevoked(contexts: TokenRevocationContext[]): Promise<boolean[]>;
|
|
19
|
+
/** Number of live revocations (expired entries may linger until a sweep). */
|
|
20
|
+
get size(): number;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../../src/revocation/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAI3E,qBAAa,qBAAsB,YAAW,eAAe;;IAK5D;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAa7C,SAAS,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB5D,YAAY,CAAC,QAAQ,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAI1E,6EAA6E;IAC7E,IAAI,IAAI,IAAI,MAAM,CAEjB;CAkBD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revocation contract.
|
|
3
|
+
*
|
|
4
|
+
* A {@link RevocationStore} answers "has this token been revoked?" and is
|
|
5
|
+
* consulted by `jwtVerify` *only after* signature and claims checks pass
|
|
6
|
+
* (LW-rev.3), so unauthenticated input can never drive store lookups.
|
|
7
|
+
* Store errors fail closed (LW-rev.4).
|
|
8
|
+
*
|
|
9
|
+
* The interface is shaped for async backends (Redis, a database): see
|
|
10
|
+
* `MemoryRevocationStore` for the reference implementation and the
|
|
11
|
+
* eviction contract - a revocation only needs to outlive its token.
|
|
12
|
+
*/
|
|
13
|
+
import type { TokenRevocationContext } from "../types.js";
|
|
14
|
+
export type { RevocationStore, TokenRevocationContext } from "../types.js";
|
|
15
|
+
/** Extract the revocation-relevant slice of a verified payload. */
|
|
16
|
+
export declare function buildRevocationContext(payload: Record<string, unknown>): TokenRevocationContext;
|
|
17
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../src/revocation/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAc,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAEtE,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE3E,mEAAmE;AACnE,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,sBAAsB,CAOxB"}
|