@frontmcp/auth 1.5.3 → 1.5.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/authorization/dcr-client.registry.d.ts +48 -3
- package/authorization/dcr-client.registry.d.ts.map +1 -1
- package/cimd/cimd.service.d.ts.map +1 -1
- package/cimd/cimd.validator.d.ts +32 -0
- package/cimd/cimd.validator.d.ts.map +1 -1
- package/esm/index.mjs +6408 -6098
- package/esm/package.json +5 -5
- package/index.js +6398 -6088
- package/jwks/jwks.service.d.ts +15 -0
- package/jwks/jwks.service.d.ts.map +1 -1
- package/jwks/jwks.types.d.ts +17 -1
- package/jwks/jwks.types.d.ts.map +1 -1
- package/options/app-auth.schema.d.ts +10 -2
- package/options/app-auth.schema.d.ts.map +1 -1
- package/options/interfaces.d.ts +61 -0
- package/options/interfaces.d.ts.map +1 -1
- package/options/orchestrated.schema.d.ts +16 -6
- package/options/orchestrated.schema.d.ts.map +1 -1
- package/options/schema.d.ts +10 -2
- package/options/schema.d.ts.map +1 -1
- package/options/shared.schemas.d.ts +5 -0
- package/options/shared.schemas.d.ts.map +1 -1
- package/options/transparent.schema.d.ts +3 -0
- package/options/transparent.schema.d.ts.map +1 -1
- package/package.json +5 -5
- package/session/authorization.store.d.ts +37 -3
- package/session/authorization.store.d.ts.map +1 -1
- package/session/storage-authorization.store.d.ts +1 -1
- package/session/storage-authorization.store.d.ts.map +1 -1
- package/utils/audience.validator.d.ts.map +1 -1
|
@@ -39,6 +39,15 @@ export interface DcrRegistryConfig {
|
|
|
39
39
|
allowedClientIds?: string[];
|
|
40
40
|
initialAccessToken?: string;
|
|
41
41
|
clients?: PreRegisteredClientInput[];
|
|
42
|
+
/**
|
|
43
|
+
* Maximum number of DYNAMICALLY-registered (DCR) clients kept in memory.
|
|
44
|
+
* Once the cap is reached, further dynamic registrations are REJECTED (rather
|
|
45
|
+
* than evicting an existing client), so every already-registered client —
|
|
46
|
+
* including confidential ones — is preserved. Pre-registered / declarative
|
|
47
|
+
* clients never count toward this cap and are never rejected. Defaults to
|
|
48
|
+
* 1000. Guards against unbounded growth from unauthenticated DCR.
|
|
49
|
+
*/
|
|
50
|
+
maxDynamicClients?: number;
|
|
42
51
|
}
|
|
43
52
|
/**
|
|
44
53
|
* Local-AS DCR client registry. Seeded from `dcr.clients` at construction and
|
|
@@ -47,16 +56,52 @@ export interface DcrRegistryConfig {
|
|
|
47
56
|
export declare class DcrClientRegistry {
|
|
48
57
|
private readonly config;
|
|
49
58
|
private readonly clients;
|
|
50
|
-
|
|
59
|
+
/** Configured redirect_uri allowlist globs (matched via `globMatch`). */
|
|
60
|
+
private readonly redirectGlobs;
|
|
51
61
|
constructor(config?: DcrRegistryConfig);
|
|
52
62
|
/** Seed `dcr.clients` so the authorize/token flows accept them without DCR. */
|
|
53
63
|
private seedPreRegisteredClients;
|
|
54
64
|
/** Look up a client by id (pre-registered or dynamically registered). */
|
|
55
65
|
get(clientId: string): RegisteredClient | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Authenticate a client at the token endpoint (RFC 6749 §2.3 / §3.2.1).
|
|
68
|
+
*
|
|
69
|
+
* - `'unknown'` — the client id is not registered (caller decides; today's
|
|
70
|
+
* public / CIMD clients are unregistered and treated as "no secret to
|
|
71
|
+
* verify").
|
|
72
|
+
* - `'ok'` — public client (`none`), or a confidential client whose
|
|
73
|
+
* presented secret matched (constant-time).
|
|
74
|
+
* - `'invalid'` — a confidential client with a missing or wrong secret. The
|
|
75
|
+
* caller MUST reject with `invalid_client`.
|
|
76
|
+
*
|
|
77
|
+
* SECURITY: previously the token endpoint verified only `client_id` equality,
|
|
78
|
+
* so a DCR-minted `client_secret` was never checked and a "confidential"
|
|
79
|
+
* client was effectively public. This restores confidential-client
|
|
80
|
+
* authentication with a timing-safe comparison.
|
|
81
|
+
*/
|
|
82
|
+
verifyClientSecret(clientId: string, presentedSecret: string | undefined): 'unknown' | 'ok' | 'invalid';
|
|
56
83
|
/** Whether a client id is known to the registry. */
|
|
57
84
|
has(clientId: string): boolean;
|
|
58
|
-
/**
|
|
59
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Add a dynamically-registered client (called by the register flow).
|
|
87
|
+
*
|
|
88
|
+
* @returns `true` if the client was registered, `false` if the dynamic-client
|
|
89
|
+
* capacity is already reached.
|
|
90
|
+
*
|
|
91
|
+
* SECURITY: `POST /oauth/register` may be unauthenticated (no
|
|
92
|
+
* `initialAccessToken`); without a bound an attacker can register unlimited
|
|
93
|
+
* clients and exhaust memory. Once the cap is reached we REJECT new dynamic
|
|
94
|
+
* registrations rather than evicting an existing one — this preserves every
|
|
95
|
+
* already-registered client (including confidential ones with a
|
|
96
|
+
* `client_secret`), which eviction would have silently invalidated. The
|
|
97
|
+
* register flow surfaces `false` as a `temporarily_unavailable` error.
|
|
98
|
+
* Pre-registered / declarative clients are exempt and never count toward the
|
|
99
|
+
* cap.
|
|
100
|
+
*/
|
|
101
|
+
register(client: RegisteredClient): boolean;
|
|
102
|
+
/** Configured dynamic-client cap, falling back to the default when invalid. */
|
|
103
|
+
private dynamicClientCap;
|
|
104
|
+
private countDynamicClients;
|
|
60
105
|
/** Whether a redirect_uri allowlist is configured. */
|
|
61
106
|
hasRedirectAllowlist(): boolean;
|
|
62
107
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dcr-client.registry.d.ts","sourceRoot":"","sources":["../../src/authorization/dcr-client.registry.ts"],"names":[],"mappings":"AAgBA,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0BAA0B,EACtB,MAAM,GACN,qBAAqB,GACrB,oBAAoB,GACpB,iBAAiB,GACjB,iBAAiB,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,GAAG,EAAE,OAAO,CAAC;IACb,uEAAuE;IACvE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qEAAqE;AACrE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uBAAuB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,oBAAoB,CAAC;IAChF,UAAU,CAAC,EAAE,KAAK,CAAC,oBAAoB,GAAG,eAAe,CAAC,CAAC;IAC3D,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,wBAAwB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"dcr-client.registry.d.ts","sourceRoot":"","sources":["../../src/authorization/dcr-client.registry.ts"],"names":[],"mappings":"AAgBA,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0BAA0B,EACtB,MAAM,GACN,qBAAqB,GACrB,oBAAoB,GACpB,iBAAiB,GACjB,iBAAiB,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,GAAG,EAAE,OAAO,CAAC;IACb,uEAAuE;IACvE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qEAAqE;AACrE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uBAAuB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,oBAAoB,CAAC;IAChF,UAAU,CAAC,EAAE,KAAK,CAAC,oBAAoB,GAAG,eAAe,CAAC,CAAC;IAC3D,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,wBAAwB,EAAE,CAAC;IACrC;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAoHD;;;GAGG;AACH,qBAAa,iBAAiB;IAKhB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuB;gBAExB,MAAM,GAAE,iBAAsB;IAK3D,+EAA+E;IAC/E,OAAO,CAAC,wBAAwB;IAoBhC,yEAAyE;IACzE,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAInD;;;;;;;;;;;;;;;OAeG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS;IAcvG,oDAAoD;IACpD,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI9B;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO;IAY3C,+EAA+E;IAC/E,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,mBAAmB;IAM3B,sDAAsD;IACtD,oBAAoB,IAAI,OAAO;IAI/B;;;OAGG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAOlD,mDAAmD;IACnD,oBAAoB,IAAI,OAAO;IAI/B;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQ5C,wEAAwE;IACxE,0BAA0B,IAAI,OAAO;IAIrC;;;;OAIG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;CAajE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cimd.service.d.ts","sourceRoot":"","sources":["../../src/cimd/cimd.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cimd.service.d.ts","sourceRoot":"","sources":["../../src/cimd/cimd.service.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAQL,KAAK,eAAe,EAEpB,KAAK,oBAAoB,EAEzB,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAC;AAGtB;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoB;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IAEpC;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;;;OAKG;gBACS,MAAM,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC;IA4BlE;;;;;OAKG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;;;;;OAQG;IACG,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAoD5E;;;;;;OAMG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,IAAI;IAUhF;;;;OAIG;IACG,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlD;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAMhD;;;;OAIG;YACW,qBAAqB;IAoKnC;;OAEG;YACW,qBAAqB;IAyCnC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;CAiBzB"}
|
package/cimd/cimd.validator.d.ts
CHANGED
|
@@ -35,6 +35,38 @@ interface SsrfCheckResult {
|
|
|
35
35
|
* @returns Result indicating if the hostname is allowed
|
|
36
36
|
*/
|
|
37
37
|
export declare function checkSsrfProtection(hostname: string): SsrfCheckResult;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a hostname via DNS and validate EVERY resolved address against the
|
|
40
|
+
* private/reserved-range blocklist — the DNS-aware complement to
|
|
41
|
+
* {@link checkSsrfProtection}.
|
|
42
|
+
*
|
|
43
|
+
* SECURITY (SSRF): `checkSsrfProtection` alone only inspects literal-IP and
|
|
44
|
+
* localhost-string hostnames; a hostname like `metadata.attacker.example` whose
|
|
45
|
+
* A-record points at `169.254.169.254` / `10.x` / `127.x` passes it untouched
|
|
46
|
+
* and the subsequent `fetch()` then connects to the internal address. This
|
|
47
|
+
* function closes that gap by resolving the name and rejecting if ANY resolved
|
|
48
|
+
* address is internal.
|
|
49
|
+
*
|
|
50
|
+
* Residual risk (documented, not yet closed here): DNS rebinding — the resolver
|
|
51
|
+
* used here and the resolver used by `fetch()` are distinct, so a TOCTOU
|
|
52
|
+
* attacker could return a public IP to this check and an internal IP to the
|
|
53
|
+
* fetch. Fully closing it requires pinning the socket to the validated IP
|
|
54
|
+
* (custom undici `lookup`/dispatcher), which is left to the caller/runtime.
|
|
55
|
+
*
|
|
56
|
+
* Degrades gracefully when `node:dns` is unavailable (e.g. a V8-isolate runtime)
|
|
57
|
+
* or the name fails to resolve: an unresolvable name cannot be reached by
|
|
58
|
+
* `fetch()` either, so we fall back to the literal-IP checks that already ran.
|
|
59
|
+
*/
|
|
60
|
+
export declare function resolveAndCheckHostname(hostname: string): Promise<SsrfCheckResult>;
|
|
61
|
+
/**
|
|
62
|
+
* Throwing wrapper around {@link resolveAndCheckHostname} for CIMD fetch paths.
|
|
63
|
+
* Must be called immediately before each outbound `fetch` (initial URL AND every
|
|
64
|
+
* redirect hop) so an attacker-supplied `client_id` host cannot resolve to an
|
|
65
|
+
* internal address.
|
|
66
|
+
*
|
|
67
|
+
* @throws CimdSecurityError if the host (or any resolved address) is internal.
|
|
68
|
+
*/
|
|
69
|
+
export declare function assertHostNotSsrf(hostname: string, clientId: string): Promise<void>;
|
|
38
70
|
/**
|
|
39
71
|
* Check if any redirect URIs in the list are localhost-only.
|
|
40
72
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cimd.validator.d.ts","sourceRoot":"","sources":["../../src/cimd/cimd.validator.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,UAAQ,GAAG,OAAO,CA4B/E;AAUD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,GAAG,CA6DvG;AAED;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAqBrE;
|
|
1
|
+
{"version":3,"file":"cimd.validator.d.ts","sourceRoot":"","sources":["../../src/cimd/cimd.validator.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,UAAQ,GAAG,OAAO,CA4B/E;AAUD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,GAAG,CA6DvG;AAED;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAqBrE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAgDxF;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKzF;AAgLD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAgB5E"}
|