@kya-os/mcp-i-cloudflare 1.13.2 → 1.13.4
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/README.md +8 -4
- package/dist/agent.d.ts +7 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +73 -7
- package/dist/agent.js.map +1 -1
- package/dist/constants/storage-keys.d.ts +37 -0
- package/dist/constants/storage-keys.d.ts.map +1 -1
- package/dist/constants/storage-keys.js +50 -0
- package/dist/constants/storage-keys.js.map +1 -1
- package/dist/runtime/oauth-handler.d.ts.map +1 -1
- package/dist/runtime/oauth-handler.js +91 -12
- package/dist/runtime/oauth-handler.js.map +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +17 -0
- package/dist/runtime.js.map +1 -1
- package/dist/services/batch-queue.d.ts +3 -1
- package/dist/services/batch-queue.d.ts.map +1 -1
- package/dist/services/batch-queue.js +16 -10
- package/dist/services/batch-queue.js.map +1 -1
- package/dist/services/consent.service.d.ts +117 -0
- package/dist/services/consent.service.d.ts.map +1 -1
- package/dist/services/consent.service.js +482 -41
- package/dist/services/consent.service.js.map +1 -1
- package/dist/services/delegation.service.d.ts.map +1 -1
- package/dist/services/delegation.service.js +4 -0
- package/dist/services/delegation.service.js.map +1 -1
- package/dist/utils/hidden-consent-tools.d.ts +37 -0
- package/dist/utils/hidden-consent-tools.d.ts.map +1 -0
- package/dist/utils/hidden-consent-tools.js +60 -0
- package/dist/utils/hidden-consent-tools.js.map +1 -0
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -332,14 +332,18 @@ The framework includes built-in CSRF (Cross-Site Request Forgery) protection for
|
|
|
332
332
|
|
|
333
333
|
#### Configuration
|
|
334
334
|
|
|
335
|
-
CSRF protection is automatically enabled when `DELEGATION_STORAGE` KV namespace is configured.
|
|
335
|
+
CSRF protection is automatically enabled when `DELEGATION_STORAGE` KV namespace is configured.
|
|
336
|
+
|
|
337
|
+
**`OAUTH_ENCRYPTION_SECRET` is REQUIRED.** It was previously optional (token encryption only), but the consent auth-gate fix made every check that depends on it **fail closed**: CSRF validation, CSRF token minting, and identity-assertion mint/verify all refuse rather than degrade when it is unset. A worker without it will **403 every delegation mint and 500 the credential render** — the consent flow does not work at all.
|
|
338
|
+
|
|
339
|
+
Set it as a **secret**, not a committed var:
|
|
336
340
|
|
|
337
341
|
```bash
|
|
338
|
-
|
|
339
|
-
[env.production.vars]
|
|
340
|
-
OAUTH_ENCRYPTION_SECRET = "your-encryption-secret-here"
|
|
342
|
+
wrangler secret put OAUTH_ENCRYPTION_SECRET
|
|
341
343
|
```
|
|
342
344
|
|
|
345
|
+
Both surfaces resolve to `env.OAUTH_ENCRYPTION_SECRET`, so a `[vars]` entry does satisfy the runtime — but it commits the value to source control, so prefer `wrangler secret put` (or your platform's secret store). Managed deployments have this provisioned automatically; see `docs/security/consent-approve-gate-verification.md`.
|
|
346
|
+
|
|
343
347
|
#### Backward Compatibility
|
|
344
348
|
|
|
345
349
|
If `OAuthSecurityService` is not available (e.g., `DELEGATION_STORAGE` not configured), the framework falls back to base64-encoded state parameters. This maintains backward compatibility but provides less security. **For production deployments, always configure `DELEGATION_STORAGE`.**
|
package/dist/agent.d.ts
CHANGED
|
@@ -236,6 +236,11 @@ export declare abstract class MCPICloudflareAgent extends McpAgent {
|
|
|
236
236
|
/**
|
|
237
237
|
* Build tool execution context with IDP token (Phase 1 - MH-7)
|
|
238
238
|
*
|
|
239
|
+
* @param delegationAuthorizationType - The stored authorization type of the
|
|
240
|
+
* presented delegation (from `getDelegationFromStorage`), or undefined for
|
|
241
|
+
* legacy records. Used by the delegation-only fallbacks below to reject a
|
|
242
|
+
* delegation whose type does not satisfy the tool's required type (security
|
|
243
|
+
* fix: consent-approve auth-gate, Task B3).
|
|
239
244
|
* @private
|
|
240
245
|
*/
|
|
241
246
|
private buildToolContext;
|
|
@@ -329,6 +334,7 @@ export declare abstract class MCPICloudflareAgent extends McpAgent {
|
|
|
329
334
|
delegationId: string;
|
|
330
335
|
userDid?: string;
|
|
331
336
|
agentDid: string;
|
|
337
|
+
authorizationType?: string;
|
|
332
338
|
}): Promise<void>;
|
|
333
339
|
/**
|
|
334
340
|
* Retrieve delegation from DO internal storage
|
|
@@ -352,6 +358,7 @@ export declare abstract class MCPICloudflareAgent extends McpAgent {
|
|
|
352
358
|
delegationId: string;
|
|
353
359
|
userDid?: string;
|
|
354
360
|
agentDid: string;
|
|
361
|
+
authorizationType?: string;
|
|
355
362
|
storedAt: number;
|
|
356
363
|
} | undefined>;
|
|
357
364
|
/**
|
package/dist/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,EACV,kBAAkB,EAClB,sBAAsB,EACtB,WAAW,EACZ,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAe9C,OAAO,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/agent.js
CHANGED
|
@@ -22,12 +22,13 @@ import { DEFAULT_SESSION_TTL } from "./constants";
|
|
|
22
22
|
import { buildNeedsAuthorizationMeta } from "./needs-authorization-meta";
|
|
23
23
|
import { z } from "zod";
|
|
24
24
|
import { generateDidKeyFromBase64, logger } from "@kya-os/mcp";
|
|
25
|
-
import { OAuthService, IdpTokenResolver, ToolContextBuilder, OAuthRequiredError, DelegationRequiredError, DelegationErrorFormatter, SessionRegistrationService, SESSION_ID_PREFIX, recordWireForm, generateResumeToken, } from "@kya-os/mcp-i-runtime"; // product layer — stays (C2/C3)
|
|
25
|
+
import { OAuthService, IdpTokenResolver, ToolContextBuilder, OAuthRequiredError, DelegationRequiredError, DelegationErrorFormatter, SessionRegistrationService, SESSION_ID_PREFIX, recordWireForm, generateResumeToken, authTypeSatisfies, isUnsatisfiableAuthType, MINTABLE_AUTH_TYPES, } from "@kya-os/mcp-i-runtime"; // product layer — stays (C2/C3)
|
|
26
26
|
import { WebCryptoProvider } from "./providers/crypto";
|
|
27
27
|
// CRITICAL: Import the OAuth service registry - this triggers globalThis registration
|
|
28
28
|
// at module load time, preventing esbuild from tree-shaking the OAuth services
|
|
29
29
|
import { getOAuthServices, isOAuthServicesAvailable, } from "./utils/oauth-service-registry";
|
|
30
30
|
import { KVOAuthConfigCache } from "./cache/kv-oauth-config-cache";
|
|
31
|
+
import { hideConsentToolsFromListing } from "./utils/hidden-consent-tools";
|
|
31
32
|
import { IdpTokenStorage } from "./services/idp-token-storage";
|
|
32
33
|
import { OAuthSecurityService } from "./services/oauth-security.service";
|
|
33
34
|
import { WorkersFetchProvider } from "./providers/storage";
|
|
@@ -1110,6 +1111,12 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
1110
1111
|
});
|
|
1111
1112
|
return credentialAuthHandler(args);
|
|
1112
1113
|
});
|
|
1114
|
+
// The consent tools above stay callable (the iframe invokes them via
|
|
1115
|
+
// tools/call) but must not leak into tools/list, where clients render
|
|
1116
|
+
// them and models call them despite the DO-NOT-CALL description.
|
|
1117
|
+
if (!hideConsentToolsFromListing(this.server)) {
|
|
1118
|
+
logger.warn("[MCPICloudflareAgent] Could not hide internal consent tools from tools/list (no handler found)");
|
|
1119
|
+
}
|
|
1113
1120
|
logger.info("[MCPICloudflareAgent] Registered MCP Apps consent UI resource");
|
|
1114
1121
|
}
|
|
1115
1122
|
catch {
|
|
@@ -1403,6 +1410,12 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
1403
1410
|
let delegationId;
|
|
1404
1411
|
let userDid;
|
|
1405
1412
|
let clientDid;
|
|
1413
|
+
// SECURITY (consent-approve auth-gate, Task B2/B3): the presented
|
|
1414
|
+
// delegation's own authorization type, surfaced from storage so the gate in
|
|
1415
|
+
// buildToolContext can require it to satisfy the tool's required type.
|
|
1416
|
+
// Remains undefined for the KV-legacy / JWT-extraction fallbacks below (no
|
|
1417
|
+
// stored type) → fail-safe re-challenge on typed tools.
|
|
1418
|
+
let delegationAuthorizationType;
|
|
1406
1419
|
try {
|
|
1407
1420
|
const agentDid = (await this.mcpiRuntime.getIdentity()).did;
|
|
1408
1421
|
logger.debug("[MCPICloudflareAgent] 🔍 Starting delegation lookup (DO storage):", {
|
|
@@ -1424,6 +1437,8 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
1424
1437
|
if (doData) {
|
|
1425
1438
|
delegationToken = doData.delegationToken;
|
|
1426
1439
|
delegationId = doData.delegationId;
|
|
1440
|
+
// Task B2: surface the stored delegation auth type for the call-time gate
|
|
1441
|
+
delegationAuthorizationType = doData.authorizationType;
|
|
1427
1442
|
// Prefer userDid from DO storage if available
|
|
1428
1443
|
if (doData.userDid) {
|
|
1429
1444
|
userDid = doData.userDid;
|
|
@@ -1442,9 +1457,17 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
1442
1457
|
const kvToken = await delegationStorage.get(userAgentKey, "text");
|
|
1443
1458
|
if (kvToken) {
|
|
1444
1459
|
delegationToken = kvToken;
|
|
1460
|
+
// Recover the delegation's auth type from its sidecar key so this
|
|
1461
|
+
// fallback can satisfy a typed tool. Records written before the
|
|
1462
|
+
// sidecar existed have none — that stays undefined and the gate
|
|
1463
|
+
// fails safe (re-challenge), which is the pre-existing behaviour
|
|
1464
|
+
// for legacy records, not a new rejection.
|
|
1465
|
+
delegationAuthorizationType =
|
|
1466
|
+
(await delegationStorage.get(STORAGE_KEYS.delegationAuthType(userDid, agentDid), "text")) ?? undefined;
|
|
1445
1467
|
logger.debug("[MCPICloudflareAgent] ✅ Delegation found in KV (legacy):", {
|
|
1446
1468
|
sessionId: sessionId.slice(0, 20) + "...",
|
|
1447
1469
|
source: "kv-fallback",
|
|
1470
|
+
hasAuthorizationType: !!delegationAuthorizationType,
|
|
1448
1471
|
});
|
|
1449
1472
|
}
|
|
1450
1473
|
}
|
|
@@ -1534,7 +1557,7 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
1534
1557
|
// Store AuthRequiredError to throw inside the inner try block where its handler lives
|
|
1535
1558
|
let pendingAuthRequiredError = null;
|
|
1536
1559
|
try {
|
|
1537
|
-
toolContext = await this.buildToolContext(toolName, userDid, sessionId, delegationToken, mappedEnv);
|
|
1560
|
+
toolContext = await this.buildToolContext(toolName, userDid, sessionId, delegationToken, delegationAuthorizationType, mappedEnv);
|
|
1538
1561
|
}
|
|
1539
1562
|
catch (error) {
|
|
1540
1563
|
// Handle CredentialAuthModeError - build consent page URL (not OAuth URL)
|
|
@@ -1893,9 +1916,14 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
1893
1916
|
/**
|
|
1894
1917
|
* Build tool execution context with IDP token (Phase 1 - MH-7)
|
|
1895
1918
|
*
|
|
1919
|
+
* @param delegationAuthorizationType - The stored authorization type of the
|
|
1920
|
+
* presented delegation (from `getDelegationFromStorage`), or undefined for
|
|
1921
|
+
* legacy records. Used by the delegation-only fallbacks below to reject a
|
|
1922
|
+
* delegation whose type does not satisfy the tool's required type (security
|
|
1923
|
+
* fix: consent-approve auth-gate, Task B3).
|
|
1896
1924
|
* @private
|
|
1897
1925
|
*/
|
|
1898
|
-
async buildToolContext(toolName, userDid, sessionId, delegationToken, env) {
|
|
1926
|
+
async buildToolContext(toolName, userDid, sessionId, delegationToken, delegationAuthorizationType, env) {
|
|
1899
1927
|
// Only build context if userDid is available and AgentShield API is configured.
|
|
1900
1928
|
// Note: DELEGATION_STORAGE is only required for password/OAuth paths, not apikey vault.
|
|
1901
1929
|
if (!userDid || !env.AGENTSHIELD_API_KEY) {
|
|
@@ -1987,7 +2015,20 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
1987
2015
|
else {
|
|
1988
2016
|
// No password auth token found - check if delegation exists
|
|
1989
2017
|
// If delegation exists, tool can still execute without credential token
|
|
1990
|
-
|
|
2018
|
+
//
|
|
2019
|
+
// SECURITY (consent-approve auth-gate, Task B3): the delegation only
|
|
2020
|
+
// authorizes this tool if its OWN authorization type satisfies the
|
|
2021
|
+
// requirement. We are provably in the password branch (isPasswordAuth
|
|
2022
|
+
// above), so the effective requirement is "password" — fall back to it
|
|
2023
|
+
// when the tool uses the legacy `oauthProvider: "credentials"` shape
|
|
2024
|
+
// (authorization.type undefined). A mismatched delegation (e.g. an
|
|
2025
|
+
// anonymous `none` consent-only delegation — the demonstrated exploit
|
|
2026
|
+
// — or a legacy record with no persisted type → undefined) does NOT
|
|
2027
|
+
// satisfy it; fall through to OAuthRequiredError so the tool
|
|
2028
|
+
// re-challenges instead of executing on mere delegation presence.
|
|
2029
|
+
const requiredAuthType = protection.authorization?.type ?? "password";
|
|
2030
|
+
if (delegationToken &&
|
|
2031
|
+
authTypeSatisfies(delegationAuthorizationType, requiredAuthType)) {
|
|
1991
2032
|
if (this._environment === "development") {
|
|
1992
2033
|
logger.debug("[MCPICloudflareAgent] No credential token found, but delegation exists - returning minimal context:", {
|
|
1993
2034
|
tool: toolName,
|
|
@@ -2007,7 +2048,31 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
2007
2048
|
delegationToken,
|
|
2008
2049
|
};
|
|
2009
2050
|
}
|
|
2010
|
-
|
|
2051
|
+
if (delegationToken) {
|
|
2052
|
+
// A delegation WAS presented but its type does not satisfy the
|
|
2053
|
+
// password requirement — log the rejection before re-challenging.
|
|
2054
|
+
// NOT gated on development: this fires only on a rejection (so it
|
|
2055
|
+
// is low volume), and it is the only signal that explains why a
|
|
2056
|
+
// user is being re-challenged. Hiding it in production made the
|
|
2057
|
+
// exact loop this follow-up addresses undiagnosable.
|
|
2058
|
+
logger.warn("[MCPICloudflareAgent] Delegation present but auth-type does not satisfy password requirement - re-challenging:", {
|
|
2059
|
+
tool: toolName,
|
|
2060
|
+
requiredAuthType,
|
|
2061
|
+
delegationAuthorizationType: delegationAuthorizationType ?? null,
|
|
2062
|
+
});
|
|
2063
|
+
// Distinguish "re-authenticate and this resolves" from "no mint
|
|
2064
|
+
// can ever satisfy this". Diagnostic only — the authorization
|
|
2065
|
+
// decision above is unchanged.
|
|
2066
|
+
if (isUnsatisfiableAuthType(requiredAuthType)) {
|
|
2067
|
+
logger.warn("[MCPICloudflareAgent] MISCONFIGURATION: tool requires an authorization type no delegation mint can produce - this tool will re-challenge forever:", {
|
|
2068
|
+
tool: toolName,
|
|
2069
|
+
requiredAuthType,
|
|
2070
|
+
mintableAuthTypes: [...MINTABLE_AUTH_TYPES],
|
|
2071
|
+
hint: "Set the tool's authorization.type to one of the mintable types, or add mint support for the required type.",
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
// No (satisfying) delegation token - throw OAuthRequiredError to trigger auth flow
|
|
2011
2076
|
if (this._environment === "development") {
|
|
2012
2077
|
logger.warn("[MCPICloudflareAgent] No password auth token found, throwing OAuthRequiredError:", {
|
|
2013
2078
|
tool: toolName,
|
|
@@ -2223,7 +2288,7 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
2223
2288
|
projectId,
|
|
2224
2289
|
});
|
|
2225
2290
|
// Build context
|
|
2226
|
-
return await contextBuilder.buildContext(toolName, userDid, sessionId, delegationToken, protection);
|
|
2291
|
+
return await contextBuilder.buildContext(toolName, userDid, sessionId, delegationToken, protection, delegationAuthorizationType);
|
|
2227
2292
|
}
|
|
2228
2293
|
catch (error) {
|
|
2229
2294
|
// Re-throw OAuthRequiredError so it can be handled by executeToolWithProof
|
|
@@ -3016,12 +3081,13 @@ export class MCPICloudflareAgent extends McpAgent {
|
|
|
3016
3081
|
* @param data - Delegation data to store
|
|
3017
3082
|
*/
|
|
3018
3083
|
async storeDelegationToStorage(data) {
|
|
3019
|
-
const { sessionId, delegationToken, delegationId, userDid, agentDid } = data;
|
|
3084
|
+
const { sessionId, delegationToken, delegationId, userDid, agentDid, authorizationType, } = data;
|
|
3020
3085
|
const storageData = {
|
|
3021
3086
|
delegationToken,
|
|
3022
3087
|
delegationId,
|
|
3023
3088
|
userDid,
|
|
3024
3089
|
agentDid,
|
|
3090
|
+
authorizationType,
|
|
3025
3091
|
storedAt: Date.now(),
|
|
3026
3092
|
};
|
|
3027
3093
|
// Store with session key (primary for tool execution)
|