mcp-trellis 1.0.0 → 2.2.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/README.md +65 -93
- package/dist/adapters/node-request.d.ts +53 -0
- package/dist/adapters/node-request.d.ts.map +1 -0
- package/dist/adapters/node-request.js +165 -0
- package/dist/adapters/node-request.js.map +1 -0
- package/dist/adapters/node.d.ts +13 -30
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +55 -101
- package/dist/adapters/node.js.map +1 -1
- package/dist/advanced.d.ts +18 -0
- package/dist/advanced.d.ts.map +1 -0
- package/dist/advanced.js +18 -0
- package/dist/advanced.js.map +1 -0
- package/dist/app-options.d.ts +132 -0
- package/dist/app-options.d.ts.map +1 -0
- package/dist/app-options.js +2 -0
- package/dist/app-options.js.map +1 -0
- package/dist/app.d.ts +2 -89
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +143 -63
- package/dist/app.js.map +1 -1
- package/dist/audit.d.ts +5 -5
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +19 -8
- package/dist/audit.js.map +1 -1
- package/dist/auth/bearer.d.ts +4 -1
- package/dist/auth/bearer.d.ts.map +1 -1
- package/dist/auth/bearer.js +19 -4
- package/dist/auth/bearer.js.map +1 -1
- package/dist/auth/signed-token.d.ts +26 -0
- package/dist/auth/signed-token.d.ts.map +1 -0
- package/dist/auth/signed-token.js +96 -0
- package/dist/auth/signed-token.js.map +1 -0
- package/dist/clients.js +1 -1
- package/dist/clients.js.map +1 -1
- package/dist/deprecated.d.ts +42 -0
- package/dist/deprecated.d.ts.map +1 -0
- package/dist/deprecated.js +35 -0
- package/dist/deprecated.js.map +1 -0
- package/dist/{body.d.ts → http/body.d.ts} +27 -6
- package/dist/http/body.d.ts.map +1 -0
- package/dist/{body.js → http/body.js} +33 -13
- package/dist/http/body.js.map +1 -0
- package/dist/http/http.d.ts +42 -0
- package/dist/http/http.d.ts.map +1 -0
- package/dist/http/http.js +100 -0
- package/dist/http/http.js.map +1 -0
- package/dist/http/origins.d.ts +37 -0
- package/dist/http/origins.d.ts.map +1 -0
- package/dist/http/origins.js +87 -0
- package/dist/http/origins.js.map +1 -0
- package/dist/{dispatch.d.ts → mcp/dispatch.d.ts} +1 -1
- package/dist/mcp/dispatch.d.ts.map +1 -0
- package/dist/mcp/dispatch.js +99 -0
- package/dist/mcp/dispatch.js.map +1 -0
- package/dist/{jsonrpc.d.ts → mcp/jsonrpc.d.ts} +9 -0
- package/dist/mcp/jsonrpc.d.ts.map +1 -0
- package/dist/mcp/jsonrpc.js +88 -0
- package/dist/mcp/jsonrpc.js.map +1 -0
- package/dist/{methods.d.ts → mcp/methods.d.ts} +60 -11
- package/dist/mcp/methods.d.ts.map +1 -0
- package/dist/mcp/methods.js +84 -0
- package/dist/mcp/methods.js.map +1 -0
- package/dist/{protocol.d.ts → mcp/protocol.d.ts} +1 -3
- package/dist/mcp/protocol.d.ts.map +1 -0
- package/dist/{protocol.js → mcp/protocol.js} +1 -3
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/registry.d.ts +58 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +81 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/rpc-handlers.d.ts +11 -0
- package/dist/mcp/rpc-handlers.d.ts.map +1 -0
- package/dist/mcp/rpc-handlers.js +133 -0
- package/dist/mcp/rpc-handlers.js.map +1 -0
- package/dist/{tools.d.ts → mcp/tools.d.ts} +20 -1
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +166 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/{validate.d.ts → mcp/validate.d.ts} +18 -21
- package/dist/mcp/validate.d.ts.map +1 -0
- package/dist/{validate.js → mcp/validate.js} +59 -41
- package/dist/mcp/validate.js.map +1 -0
- package/dist/oauth/audit.d.ts +20 -0
- package/dist/oauth/audit.d.ts.map +1 -0
- package/dist/oauth/audit.js +29 -0
- package/dist/oauth/audit.js.map +1 -0
- package/dist/oauth/cimd/cimd-parse.d.ts +4 -0
- package/dist/oauth/cimd/cimd-parse.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd-parse.js +70 -0
- package/dist/oauth/cimd/cimd-parse.js.map +1 -0
- package/dist/oauth/cimd/cimd-ssrf.d.ts +8 -0
- package/dist/oauth/cimd/cimd-ssrf.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd-ssrf.js +193 -0
- package/dist/oauth/cimd/cimd-ssrf.js.map +1 -0
- package/dist/oauth/cimd/cimd.d.ts +36 -0
- package/dist/oauth/cimd/cimd.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd.js +132 -0
- package/dist/oauth/cimd/cimd.js.map +1 -0
- package/dist/oauth/cimd/types.d.ts +12 -0
- package/dist/oauth/cimd/types.d.ts.map +1 -0
- package/dist/oauth/cimd/types.js +3 -0
- package/dist/oauth/cimd/types.js.map +1 -0
- package/dist/oauth/config.d.ts +51 -0
- package/dist/oauth/config.d.ts.map +1 -0
- package/dist/oauth/config.js +108 -0
- package/dist/oauth/config.js.map +1 -0
- package/dist/oauth/constants.d.ts +11 -0
- package/dist/oauth/constants.d.ts.map +1 -1
- package/dist/oauth/constants.js +11 -0
- package/dist/oauth/constants.js.map +1 -1
- package/dist/oauth/{base64url.d.ts → crypto/base64url.d.ts} +0 -1
- package/dist/oauth/crypto/base64url.d.ts.map +1 -0
- package/dist/oauth/{base64url.js → crypto/base64url.js} +0 -1
- package/dist/oauth/crypto/base64url.js.map +1 -0
- package/dist/oauth/crypto/clientauth.d.ts +13 -0
- package/dist/oauth/crypto/clientauth.d.ts.map +1 -0
- package/dist/oauth/crypto/clientauth.js +195 -0
- package/dist/oauth/crypto/clientauth.js.map +1 -0
- package/dist/oauth/crypto/codes.d.ts +65 -0
- package/dist/oauth/crypto/codes.d.ts.map +1 -0
- package/dist/oauth/crypto/codes.js +121 -0
- package/dist/oauth/crypto/codes.js.map +1 -0
- package/dist/oauth/crypto/hkdf.d.ts +13 -0
- package/dist/oauth/crypto/hkdf.d.ts.map +1 -0
- package/dist/oauth/crypto/hkdf.js +30 -0
- package/dist/oauth/crypto/hkdf.js.map +1 -0
- package/dist/oauth/crypto/keycache.d.ts +19 -0
- package/dist/oauth/crypto/keycache.d.ts.map +1 -0
- package/dist/oauth/crypto/keycache.js +44 -0
- package/dist/oauth/crypto/keycache.js.map +1 -0
- package/dist/oauth/crypto/pkce.d.ts.map +1 -0
- package/dist/oauth/{pkce.js → crypto/pkce.js} +1 -1
- package/dist/oauth/crypto/pkce.js.map +1 -0
- package/dist/oauth/{sealed.d.ts → crypto/sealed.d.ts} +12 -3
- package/dist/oauth/crypto/sealed.d.ts.map +1 -0
- package/dist/oauth/{sealed.js → crypto/sealed.js} +22 -14
- package/dist/oauth/crypto/sealed.js.map +1 -0
- package/dist/oauth/{secrethash.d.ts → crypto/secrethash.d.ts} +14 -0
- package/dist/oauth/crypto/secrethash.d.ts.map +1 -0
- package/dist/oauth/{secrethash.js → crypto/secrethash.js} +27 -11
- package/dist/oauth/crypto/secrethash.js.map +1 -0
- package/dist/oauth/deprecated.d.ts +52 -0
- package/dist/oauth/deprecated.d.ts.map +1 -0
- package/dist/oauth/deprecated.js +49 -0
- package/dist/oauth/deprecated.js.map +1 -0
- package/dist/oauth/endpoints/authorize.d.ts +3 -0
- package/dist/oauth/endpoints/authorize.d.ts.map +1 -0
- package/dist/oauth/endpoints/authorize.js +209 -0
- package/dist/oauth/endpoints/authorize.js.map +1 -0
- package/dist/oauth/endpoints/callback.d.ts +20 -0
- package/dist/oauth/endpoints/callback.d.ts.map +1 -0
- package/dist/oauth/endpoints/callback.js +31 -0
- package/dist/oauth/endpoints/callback.js.map +1 -0
- package/dist/oauth/endpoints/consent-page.d.ts +5 -0
- package/dist/oauth/endpoints/consent-page.d.ts.map +1 -0
- package/dist/oauth/endpoints/consent-page.js +63 -0
- package/dist/oauth/endpoints/consent-page.js.map +1 -0
- package/dist/oauth/endpoints/consent.d.ts +29 -0
- package/dist/oauth/endpoints/consent.d.ts.map +1 -0
- package/dist/oauth/endpoints/consent.js +98 -0
- package/dist/oauth/endpoints/consent.js.map +1 -0
- package/dist/oauth/{metadata.d.ts → endpoints/metadata.d.ts} +8 -2
- package/dist/oauth/endpoints/metadata.d.ts.map +1 -0
- package/dist/oauth/{metadata.js → endpoints/metadata.js} +10 -4
- package/dist/oauth/endpoints/metadata.js.map +1 -0
- package/dist/oauth/endpoints/register.d.ts +10 -0
- package/dist/oauth/endpoints/register.d.ts.map +1 -0
- package/dist/oauth/endpoints/register.js +96 -0
- package/dist/oauth/endpoints/register.js.map +1 -0
- package/dist/oauth/{revoke.d.ts → endpoints/revoke.d.ts} +1 -1
- package/dist/oauth/endpoints/revoke.d.ts.map +1 -0
- package/dist/oauth/{revoke.js → endpoints/revoke.js} +8 -18
- package/dist/oauth/endpoints/revoke.js.map +1 -0
- package/dist/oauth/endpoints/token.d.ts +3 -0
- package/dist/oauth/endpoints/token.d.ts.map +1 -0
- package/dist/oauth/{token.js → endpoints/token.js} +32 -25
- package/dist/oauth/endpoints/token.js.map +1 -0
- package/dist/oauth/{wellknown.d.ts → endpoints/wellknown.d.ts} +1 -1
- package/dist/oauth/endpoints/wellknown.d.ts.map +1 -0
- package/dist/oauth/{wellknown.js → endpoints/wellknown.js} +7 -9
- package/dist/oauth/endpoints/wellknown.js.map +1 -0
- package/dist/oauth/policy/redirect.d.ts.map +1 -0
- package/dist/oauth/policy/redirect.js.map +1 -0
- package/dist/oauth/policy/reqbody.d.ts +18 -0
- package/dist/oauth/policy/reqbody.d.ts.map +1 -0
- package/dist/oauth/policy/reqbody.js +68 -0
- package/dist/oauth/policy/reqbody.js.map +1 -0
- package/dist/oauth/{resource.d.ts → policy/resource.d.ts} +1 -1
- package/dist/oauth/policy/resource.d.ts.map +1 -0
- package/dist/oauth/{resource.js → policy/resource.js} +2 -2
- package/dist/oauth/policy/resource.js.map +1 -0
- package/dist/oauth/{scope.d.ts → policy/scope.d.ts} +2 -2
- package/dist/oauth/policy/scope.d.ts.map +1 -0
- package/dist/oauth/{scope.js → policy/scope.js} +3 -3
- package/dist/oauth/policy/scope.js.map +1 -0
- package/dist/oauth/router.d.ts +10 -13
- package/dist/oauth/router.d.ts.map +1 -1
- package/dist/oauth/router.js +93 -115
- package/dist/oauth/router.js.map +1 -1
- package/dist/oauth/types.d.ts +99 -45
- package/dist/oauth/types.d.ts.map +1 -1
- package/dist/oauth/types.js +1 -90
- package/dist/oauth/types.js.map +1 -1
- package/dist/server.d.ts +13 -12
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -8
- package/dist/server.js.map +1 -1
- package/dist/util/defined.d.ts +11 -0
- package/dist/util/defined.d.ts.map +1 -0
- package/dist/util/defined.js +15 -0
- package/dist/util/defined.js.map +1 -0
- package/dist/util/json.d.ts +3 -0
- package/dist/util/json.d.ts.map +1 -0
- package/dist/util/json.js +3 -0
- package/dist/util/json.js.map +1 -0
- package/docs/ROADMAP.md +37 -47
- package/docs/compatibility.md +86 -0
- package/docs/diagrams/demo-tool-result.png +0 -0
- package/docs/diagrams/mcp-trellis-architecture.html +305 -0
- package/docs/guide.md +46 -16
- package/docs/reference.md +55 -22
- package/docs/security.md +58 -9
- package/docs/troubleshooting.md +19 -0
- package/package.json +27 -10
- package/dist/adapters/origins.d.ts +0 -19
- package/dist/adapters/origins.d.ts.map +0 -1
- package/dist/adapters/origins.js +0 -52
- package/dist/adapters/origins.js.map +0 -1
- package/dist/body.d.ts.map +0 -1
- package/dist/body.js.map +0 -1
- package/dist/dispatch.d.ts.map +0 -1
- package/dist/dispatch.js +0 -119
- package/dist/dispatch.js.map +0 -1
- package/dist/http.d.ts +0 -17
- package/dist/http.d.ts.map +0 -1
- package/dist/http.js +0 -38
- package/dist/http.js.map +0 -1
- package/dist/jsonrpc.d.ts.map +0 -1
- package/dist/jsonrpc.js +0 -18
- package/dist/jsonrpc.js.map +0 -1
- package/dist/methods.d.ts.map +0 -1
- package/dist/methods.js +0 -130
- package/dist/methods.js.map +0 -1
- package/dist/oauth/authorize.d.ts +0 -3
- package/dist/oauth/authorize.d.ts.map +0 -1
- package/dist/oauth/authorize.js +0 -141
- package/dist/oauth/authorize.js.map +0 -1
- package/dist/oauth/base64url.d.ts.map +0 -1
- package/dist/oauth/base64url.js.map +0 -1
- package/dist/oauth/clientauth.d.ts +0 -24
- package/dist/oauth/clientauth.d.ts.map +0 -1
- package/dist/oauth/clientauth.js +0 -119
- package/dist/oauth/clientauth.js.map +0 -1
- package/dist/oauth/codes.d.ts +0 -30
- package/dist/oauth/codes.d.ts.map +0 -1
- package/dist/oauth/codes.js +0 -85
- package/dist/oauth/codes.js.map +0 -1
- package/dist/oauth/consent.d.ts +0 -65
- package/dist/oauth/consent.d.ts.map +0 -1
- package/dist/oauth/consent.js +0 -173
- package/dist/oauth/consent.js.map +0 -1
- package/dist/oauth/metadata.d.ts.map +0 -1
- package/dist/oauth/metadata.js.map +0 -1
- package/dist/oauth/pkce.d.ts.map +0 -1
- package/dist/oauth/pkce.js.map +0 -1
- package/dist/oauth/redirect.d.ts.map +0 -1
- package/dist/oauth/redirect.js.map +0 -1
- package/dist/oauth/reqbody.d.ts +0 -10
- package/dist/oauth/reqbody.d.ts.map +0 -1
- package/dist/oauth/reqbody.js +0 -29
- package/dist/oauth/reqbody.js.map +0 -1
- package/dist/oauth/resource.d.ts.map +0 -1
- package/dist/oauth/resource.js.map +0 -1
- package/dist/oauth/revoke.d.ts.map +0 -1
- package/dist/oauth/revoke.js.map +0 -1
- package/dist/oauth/scope.d.ts.map +0 -1
- package/dist/oauth/scope.js.map +0 -1
- package/dist/oauth/sealed.d.ts.map +0 -1
- package/dist/oauth/sealed.js.map +0 -1
- package/dist/oauth/secrethash.d.ts.map +0 -1
- package/dist/oauth/secrethash.js.map +0 -1
- package/dist/oauth/token.d.ts +0 -3
- package/dist/oauth/token.d.ts.map +0 -1
- package/dist/oauth/token.js.map +0 -1
- package/dist/oauth/wellknown.d.ts.map +0 -1
- package/dist/oauth/wellknown.js.map +0 -1
- package/dist/protocol.d.ts.map +0 -1
- package/dist/protocol.js.map +0 -1
- package/dist/registry.d.ts +0 -37
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -77
- package/dist/registry.js.map +0 -1
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -98
- package/dist/tools.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- /package/dist/oauth/{pkce.d.ts → crypto/pkce.d.ts} +0 -0
- /package/dist/oauth/{redirect.d.ts → policy/redirect.d.ts} +0 -0
- /package/dist/oauth/{redirect.js → policy/redirect.js} +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invoke `ports.audit`, swallowing any failure and racing it against
|
|
3
|
+
* `auditTimeoutMs` — the OAuth-side twin of `methods.ts`'s `safeAudit`.
|
|
4
|
+
* A hanging sink must not stall `/token` or `/authorize` error responses.
|
|
5
|
+
*/
|
|
6
|
+
import { DEFAULT_AUDIT_TIMEOUT_MS, runAuditBounded } from "../http/http.js";
|
|
7
|
+
export const safeOAuthAudit = async (options, entry) => {
|
|
8
|
+
const audit = options.ports.audit;
|
|
9
|
+
if (!audit)
|
|
10
|
+
return;
|
|
11
|
+
await runAuditBounded(() => audit(entry), options.auditTimeoutMs ?? DEFAULT_AUDIT_TIMEOUT_MS);
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Fires `legacy_code_secret_used` when a value was recovered with a
|
|
15
|
+
* rotation-array entry other than the primary (`keyIndex > 0`) — the signal
|
|
16
|
+
* every codeSecret rotation site (`/authorize`, `/consent`, `/token`,
|
|
17
|
+
* `firstClientAuthError`) uses to tell an operator which old keys are still
|
|
18
|
+
* live. A no-op for the common case (`keyIndex === 0`, or none at all).
|
|
19
|
+
*/
|
|
20
|
+
export const auditLegacyKeyUsage = async (options, usage) => {
|
|
21
|
+
if (!usage.keyIndex)
|
|
22
|
+
return;
|
|
23
|
+
await safeOAuthAudit(options, {
|
|
24
|
+
event: "legacy_code_secret_used",
|
|
25
|
+
clientId: usage.clientId,
|
|
26
|
+
reason: `${usage.source} with codeSecret[${usage.keyIndex}]`,
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/oauth/audit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAG5E,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,OAA2B,EAC3B,KAAsB,EACP,EAAE;IACjB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,cAAc,IAAI,wBAAwB,CAAC,CAAC;AAChG,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACtC,OAA2B,EAC3B,KAAgF,EACjE,EAAE;IACjB,IAAI,CAAC,KAAK,CAAC,QAAQ;QAAE,OAAO;IAC5B,MAAM,cAAc,CAAC,OAAO,EAAE;QAC5B,KAAK,EAAE,yBAAyB;QAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,oBAAoB,KAAK,CAAC,QAAQ,GAAG;KAC7D,CAAC,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimd-parse.d.ts","sourceRoot":"","sources":["../../../src/oauth/cimd/cimd-parse.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,GAAG,IAAI,KAAG,MAGxD,CAAC;AAoCF,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,EAAE,MAAM,MAAM,KAAG,YAsB9D,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { isJsonObject } from "../../util/json.js";
|
|
2
|
+
import { MAX_CLIENT_REDIRECT_URIS } from "../constants.js";
|
|
3
|
+
import { isLoopbackHostname } from "./cimd-ssrf.js";
|
|
4
|
+
const DEFAULT_CACHE_SECONDS = 300;
|
|
5
|
+
const MAX_CACHE_SECONDS = 3600;
|
|
6
|
+
export const parseCacheMaxAge = (header) => {
|
|
7
|
+
const maxAge = header ? /(?:^|,)\s*max-age=(\d+)/i.exec(header)?.[1] : undefined;
|
|
8
|
+
return maxAge === undefined ? DEFAULT_CACHE_SECONDS : Math.min(Number(maxAge), MAX_CACHE_SECONDS);
|
|
9
|
+
};
|
|
10
|
+
const assertHttpRedirectUri = (uri) => {
|
|
11
|
+
let parsed;
|
|
12
|
+
try {
|
|
13
|
+
parsed = new URL(uri);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new Error("CIMD redirect_uris entries must be absolute URLs");
|
|
17
|
+
}
|
|
18
|
+
if (parsed.username || parsed.password || parsed.hash) {
|
|
19
|
+
throw new Error("CIMD redirect_uris must not carry credentials or a fragment");
|
|
20
|
+
}
|
|
21
|
+
if (parsed.protocol === "https:")
|
|
22
|
+
return;
|
|
23
|
+
if (parsed.protocol === "http:") {
|
|
24
|
+
if (!isLoopbackHostname(parsed.hostname)) {
|
|
25
|
+
throw new Error("CIMD http redirect_uris must be loopback (127.0.0.1 / ::1)");
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
throw new Error("CIMD redirect_uris must be http(s)");
|
|
30
|
+
};
|
|
31
|
+
const parseRedirectUris = (rawUris) => {
|
|
32
|
+
if (!Array.isArray(rawUris) || rawUris.length === 0) {
|
|
33
|
+
throw new Error("CIMD document must include a non-empty redirect_uris array");
|
|
34
|
+
}
|
|
35
|
+
if (rawUris.length > MAX_CLIENT_REDIRECT_URIS) {
|
|
36
|
+
throw new Error(`CIMD redirect_uris must have at most ${MAX_CLIENT_REDIRECT_URIS} entries`);
|
|
37
|
+
}
|
|
38
|
+
return rawUris.map((u) => {
|
|
39
|
+
if (typeof u !== "string" || !u)
|
|
40
|
+
throw new Error("CIMD redirect_uris entries must be strings");
|
|
41
|
+
assertHttpRedirectUri(u);
|
|
42
|
+
return u;
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
export const parseDocument = (clientId, text) => {
|
|
46
|
+
let parsed;
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(text);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throw new Error("CIMD document is not JSON");
|
|
52
|
+
}
|
|
53
|
+
if (!isJsonObject(parsed))
|
|
54
|
+
throw new Error("CIMD document must be a JSON object");
|
|
55
|
+
const record = parsed;
|
|
56
|
+
if (record.client_id !== clientId) {
|
|
57
|
+
throw new Error("CIMD document client_id must equal the request URL exactly");
|
|
58
|
+
}
|
|
59
|
+
const authMethod = record.token_endpoint_auth_method;
|
|
60
|
+
if (authMethod !== undefined && authMethod !== "none") {
|
|
61
|
+
throw new Error("CIMD clients must be public (token_endpoint_auth_method none)");
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
client_id: clientId,
|
|
65
|
+
redirect_uris: parseRedirectUris(record.redirect_uris),
|
|
66
|
+
...(typeof record.client_name === "string" ? { client_name: record.client_name } : {}),
|
|
67
|
+
token_endpoint_auth_method: "none",
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=cimd-parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimd-parse.js","sourceRoot":"","sources":["../../../src/oauth/cimd/cimd-parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSRF guards for CIMD URL fetch: hostname normalization, private/NAT64
|
|
3
|
+
* IP blocks, and DNS lookup before connect.
|
|
4
|
+
*/
|
|
5
|
+
export declare const isLoopbackHostname: (hostname: string) => boolean;
|
|
6
|
+
export declare const defaultLookup: (hostname: string) => Promise<string[]>;
|
|
7
|
+
export declare const assertSafeUrl: (url: URL, lookup: (hostname: string) => Promise<string[]>) => Promise<void>;
|
|
8
|
+
//# sourceMappingURL=cimd-ssrf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimd-ssrf.d.ts","sourceRoot":"","sources":["../../../src/oauth/cimd/cimd-ssrf.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoLH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,OAEL,CAAC;AAElD,eAAO,MAAM,aAAa,GAAU,UAAU,MAAM,KAAG,OAAO,CAAC,MAAM,EAAE,CAQtE,CAAC;AAiBF,eAAO,MAAM,aAAa,GACxB,KAAK,GAAG,EACR,QAAQ,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,KAC9C,OAAO,CAAC,IAAI,CASd,CAAC"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSRF guards for CIMD URL fetch: hostname normalization, private/NAT64
|
|
3
|
+
* IP blocks, and DNS lookup before connect.
|
|
4
|
+
*/
|
|
5
|
+
/** Strip WHATWG brackets from IPv6 hostnames (`[::1]` → `::1`). */
|
|
6
|
+
const normalizeHostname = (hostname) => {
|
|
7
|
+
const host = hostname.toLowerCase().replace(/\.$/, "");
|
|
8
|
+
return host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
|
9
|
+
};
|
|
10
|
+
const DOTTED_QUAD = /^\d{1,3}(?:\.\d{1,3}){3}$/;
|
|
11
|
+
/** Digits-and-dots only — covers shorthand (`127.1`) and decimal (`2130706433`). */
|
|
12
|
+
const IPV4_CANDIDATE = /^\d+(?:\.\d+)*$/;
|
|
13
|
+
const IPV4_PRIVATE = [
|
|
14
|
+
/^0\./,
|
|
15
|
+
/^10\./,
|
|
16
|
+
/^127\./,
|
|
17
|
+
/^169\.254\./,
|
|
18
|
+
/^172\.(1[6-9]|2\d|3[0-1])\./,
|
|
19
|
+
/^192\.168\./,
|
|
20
|
+
/^100\.(6[4-9]|[7-9]\d|1[0-1]\d|12[0-7])\./,
|
|
21
|
+
// IETF protocol assignments 192.0.0/24, benchmarking 198.18/15
|
|
22
|
+
/^192\.0\.0\./,
|
|
23
|
+
/^198\.1[89]\./,
|
|
24
|
+
// Multicast 224/4, reserved 240/4 (incl. 255.255.255.255)
|
|
25
|
+
/^(22[4-9]|23\d|24\d|25[0-5])\./,
|
|
26
|
+
];
|
|
27
|
+
const isPrivateV4 = (v4) => IPV4_PRIVATE.some((re) => re.test(v4));
|
|
28
|
+
/** IPv4-mapped (`::ffff:a.b.c.d`) and deprecated IPv4-compatible (`::a.b.c.d`) forms. */
|
|
29
|
+
const expandIpv4Mapped = (ip) => {
|
|
30
|
+
const mapped = /^::(?:ffff:)?(\d{1,3}(?:\.\d{1,3}){3})$/i.exec(ip);
|
|
31
|
+
if (mapped)
|
|
32
|
+
return mapped[1] ?? null;
|
|
33
|
+
const hexMapped = /^::(?:ffff:)?([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i.exec(ip);
|
|
34
|
+
if (!hexMapped)
|
|
35
|
+
return null;
|
|
36
|
+
const hi = Number.parseInt(hexMapped[1] ?? "", 16);
|
|
37
|
+
const lo = Number.parseInt(hexMapped[2] ?? "", 16);
|
|
38
|
+
return `${(hi >> 8) & 255}.${hi & 255}.${(lo >> 8) & 255}.${lo & 255}`;
|
|
39
|
+
};
|
|
40
|
+
const HEXTET = /^[0-9a-f]{1,4}$/i;
|
|
41
|
+
const parseHextet = (part) => HEXTET.test(part) ? Number.parseInt(part, 16) : null;
|
|
42
|
+
const hextetPairToIpv4 = (hi, lo) => {
|
|
43
|
+
const high = parseHextet(hi);
|
|
44
|
+
const low = parseHextet(lo);
|
|
45
|
+
if (high === null || low === null)
|
|
46
|
+
return null;
|
|
47
|
+
return `${(high >> 8) & 255}.${high & 255}.${(low >> 8) & 255}.${low & 255}`;
|
|
48
|
+
};
|
|
49
|
+
const splitHextetParts = (segment) => segment.length > 0 ? segment.split(":") : [];
|
|
50
|
+
const dottedQuadToHextetPair = (quad) => {
|
|
51
|
+
const octets = quad.split(".").map(Number);
|
|
52
|
+
if (octets.length !== 4 || octets.some((n) => !Number.isFinite(n) || n < 0 || n > 255)) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const [a, b, c, d] = octets;
|
|
56
|
+
return [((a << 8) | b).toString(16), ((c << 8) | d).toString(16)];
|
|
57
|
+
};
|
|
58
|
+
const isValidHextetList = (hextets) => hextets.length === 8 && hextets.every((h) => parseHextet(h) !== null);
|
|
59
|
+
/**
|
|
60
|
+
* Expand an IPv6 literal into 8 hextets. Trailing dotted-quad (mapped /
|
|
61
|
+
* compatible forms) consumes the last two slots. Returns null when the
|
|
62
|
+
* string is not a well-formed IPv6 address — callers fail closed.
|
|
63
|
+
*/
|
|
64
|
+
const expandIpv6Hextets = (ip) => {
|
|
65
|
+
if (!ip.includes(":"))
|
|
66
|
+
return null;
|
|
67
|
+
let ipv4Tail = null;
|
|
68
|
+
let core = ip;
|
|
69
|
+
const lastColon = ip.lastIndexOf(":");
|
|
70
|
+
const after = ip.slice(lastColon + 1);
|
|
71
|
+
if (DOTTED_QUAD.test(after)) {
|
|
72
|
+
ipv4Tail = dottedQuadToHextetPair(after);
|
|
73
|
+
if (!ipv4Tail)
|
|
74
|
+
return null;
|
|
75
|
+
core = ip.slice(0, lastColon);
|
|
76
|
+
}
|
|
77
|
+
const slots = 8 - (ipv4Tail ? 2 : 0);
|
|
78
|
+
if (core.includes("::")) {
|
|
79
|
+
const pieces = core.split("::");
|
|
80
|
+
if (pieces.length !== 2)
|
|
81
|
+
return null;
|
|
82
|
+
const headParts = splitHextetParts(pieces[0] ?? "");
|
|
83
|
+
const tailParts = splitHextetParts(pieces[1] ?? "");
|
|
84
|
+
if (headParts.length + tailParts.length > slots)
|
|
85
|
+
return null;
|
|
86
|
+
const missing = slots - headParts.length - tailParts.length;
|
|
87
|
+
const hextets = [
|
|
88
|
+
...headParts,
|
|
89
|
+
...Array.from({ length: missing }, () => "0"),
|
|
90
|
+
...tailParts,
|
|
91
|
+
...(ipv4Tail ?? []),
|
|
92
|
+
];
|
|
93
|
+
return isValidHextetList(hextets) ? hextets : null;
|
|
94
|
+
}
|
|
95
|
+
const parts = splitHextetParts(core);
|
|
96
|
+
if (parts.length !== slots)
|
|
97
|
+
return null;
|
|
98
|
+
const hextets = [...parts, ...(ipv4Tail ?? [])];
|
|
99
|
+
return isValidHextetList(hextets) ? hextets : null;
|
|
100
|
+
};
|
|
101
|
+
// --- block rules (ordered; first match blocks) ---
|
|
102
|
+
/** Non-canonical IPv4 from a sloppy `cimdLookup` — fail closed, not a public hostname. */
|
|
103
|
+
const isNonCanonicalIpv4 = (v4) => IPV4_CANDIDATE.test(v4) && !DOTTED_QUAD.test(v4);
|
|
104
|
+
const isPrivateDottedQuad = (v4) => DOTTED_QUAD.test(v4) && isPrivateV4(v4);
|
|
105
|
+
const IPV6_BLOCKED_EXACT = new Set(["::1", "::"]);
|
|
106
|
+
const IPV6_BLOCKED_PREFIXES = ["fe80:", "::ffff:"];
|
|
107
|
+
/** ULA fc00::/7 and multicast ff00::/8. */
|
|
108
|
+
const IPV6_BLOCKED_PREFIX_RES = [/^f[cd][0-9a-f]{2}:/i, /^ff[0-9a-f]{0,2}:/];
|
|
109
|
+
const isBlockedIpv6Literal = (ip) => IPV6_BLOCKED_EXACT.has(ip) ||
|
|
110
|
+
IPV6_BLOCKED_PREFIXES.some((prefix) => ip.startsWith(prefix)) ||
|
|
111
|
+
IPV6_BLOCKED_PREFIX_RES.some((re) => re.test(ip));
|
|
112
|
+
const leadingFiveZero = (n) => n[0] === 0 && n[1] === 0 && n[2] === 0 && n[3] === 0 && n[4] === 0;
|
|
113
|
+
/** Full-form IPv4-mapped (`0:0:0:0:0:ffff:…`) — same block as `::ffff:` prefix. */
|
|
114
|
+
const isIpv4MappedHextets = (n) => leadingFiveZero(n) && n[5] === 0xffff;
|
|
115
|
+
/** Deprecated IPv4-compatible — private/reserved embeds only (public stays). */
|
|
116
|
+
const isBlockedIpv4Compatible = (n, raw) => {
|
|
117
|
+
if (!leadingFiveZero(n) || n[5] !== 0)
|
|
118
|
+
return false;
|
|
119
|
+
if (n[6] === 0 && (n[7] === 0 || n[7] === 1))
|
|
120
|
+
return true;
|
|
121
|
+
const embedded = hextetPairToIpv4(raw[6] ?? "", raw[7] ?? "");
|
|
122
|
+
return !embedded || isPrivateV4(embedded);
|
|
123
|
+
};
|
|
124
|
+
const HEXTET_BLOCK_RULES = [
|
|
125
|
+
isIpv4MappedHextets,
|
|
126
|
+
isBlockedIpv4Compatible,
|
|
127
|
+
(n) => n[0] === 0x2002, // 6to4 2002::/16
|
|
128
|
+
(n) => n[0] === 0x64 && n[1] === 0xff9b, // NAT64 64:ff9b::/96
|
|
129
|
+
];
|
|
130
|
+
const isBlockedIp = (ip) => {
|
|
131
|
+
const normalized = normalizeHostname(ip);
|
|
132
|
+
const v4 = expandIpv4Mapped(normalized) ?? normalized;
|
|
133
|
+
if (isNonCanonicalIpv4(v4) || isPrivateDottedQuad(v4))
|
|
134
|
+
return true;
|
|
135
|
+
if (!normalized.includes(":"))
|
|
136
|
+
return false;
|
|
137
|
+
if (isBlockedIpv6Literal(normalized))
|
|
138
|
+
return true;
|
|
139
|
+
const raw = expandIpv6Hextets(normalized);
|
|
140
|
+
if (!raw)
|
|
141
|
+
return true; // fail closed on unparseable IPv6
|
|
142
|
+
const n = raw.map((h) => Number.parseInt(h, 16));
|
|
143
|
+
return HEXTET_BLOCK_RULES.some((rule) => rule(n, raw));
|
|
144
|
+
};
|
|
145
|
+
const BLOCKED_HOST_EXACT = new Set(["localhost"]);
|
|
146
|
+
const BLOCKED_HOST_SUFFIXES = [".localhost", ".local"];
|
|
147
|
+
const isBlockedHostname = (hostname) => {
|
|
148
|
+
const host = normalizeHostname(hostname);
|
|
149
|
+
if (BLOCKED_HOST_EXACT.has(host))
|
|
150
|
+
return true;
|
|
151
|
+
if (BLOCKED_HOST_SUFFIXES.some((suffix) => host.endsWith(suffix)))
|
|
152
|
+
return true;
|
|
153
|
+
return isBlockedIp(host);
|
|
154
|
+
};
|
|
155
|
+
const LOOPBACK_HOSTS = new Set(["127.0.0.1", "::1"]);
|
|
156
|
+
export const isLoopbackHostname = (hostname) =>
|
|
157
|
+
// `localhost` deliberately excluded — RFC 8252 §8.3, same as policy/redirect.ts.
|
|
158
|
+
LOOPBACK_HOSTS.has(normalizeHostname(hostname));
|
|
159
|
+
export const defaultLookup = async (hostname) => {
|
|
160
|
+
try {
|
|
161
|
+
const dns = await import("node:dns/promises");
|
|
162
|
+
const results = await dns.lookup(hostname, { all: true, verbatim: true });
|
|
163
|
+
return results.map((r) => r.address);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
throw new Error("CIMD DNS lookup unavailable");
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
const URL_SAFETY = {
|
|
170
|
+
https: {
|
|
171
|
+
ok: (url) => url.protocol === "https:",
|
|
172
|
+
error: "CIMD client_id must be https",
|
|
173
|
+
},
|
|
174
|
+
noCredentials: {
|
|
175
|
+
ok: (url) => !url.username && !url.password,
|
|
176
|
+
error: "CIMD URL must not carry credentials",
|
|
177
|
+
},
|
|
178
|
+
publicHostname: {
|
|
179
|
+
ok: (url) => !isBlockedHostname(url.hostname),
|
|
180
|
+
error: "CIMD hostname is not publicly routable",
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
export const assertSafeUrl = async (url, lookup) => {
|
|
184
|
+
for (const rule of Object.values(URL_SAFETY)) {
|
|
185
|
+
if (!rule.ok(url))
|
|
186
|
+
throw new Error(rule.error);
|
|
187
|
+
}
|
|
188
|
+
const addrs = await lookup(normalizeHostname(url.hostname));
|
|
189
|
+
if (addrs.length === 0 || addrs.some(isBlockedIp)) {
|
|
190
|
+
throw new Error("CIMD resolved to a non-public address");
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
//# sourceMappingURL=cimd-ssrf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimd-ssrf.js","sourceRoot":"","sources":["../../../src/oauth/cimd/cimd-ssrf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client ID Metadata Documents (CIMD) — HTTPS URL `client_id` metadata.
|
|
3
|
+
* Off by default (`cimd: true`). SSRF guards live in `cimd-ssrf.ts`.
|
|
4
|
+
*
|
|
5
|
+
* ponytail: DNS checked before/after fetch; TCP connect is not pinned (Web
|
|
6
|
+
* fetch). Upgrade: custom dispatcher dialing the resolved IP + Host header.
|
|
7
|
+
*/
|
|
8
|
+
import type { CimdCache, CimdDocument } from "./types.js";
|
|
9
|
+
export type { CimdCache, CimdDocument } from "./types.js";
|
|
10
|
+
export type CimdFetchOptions = {
|
|
11
|
+
/** Override fetch (tests). Defaults to globalThis.fetch. */
|
|
12
|
+
fetch?: typeof fetch;
|
|
13
|
+
cache?: CimdCache;
|
|
14
|
+
/**
|
|
15
|
+
* DNS lookup for rebinding checks. When omitted, the library tries
|
|
16
|
+
* `node:dns/promises.lookup` if available; if that is also unavailable
|
|
17
|
+
* (e.g. some Workers), resolution is refused rather than fetched blind.
|
|
18
|
+
*/
|
|
19
|
+
lookup?: (hostname: string) => Promise<string[]>;
|
|
20
|
+
/** Per-hop timeout covering connect **and** body read. Tests only — default 10 s. */
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
};
|
|
23
|
+
/** Build fetch options from router/app CIMD ports. */
|
|
24
|
+
export declare const cimdFetchOpts: (ports: {
|
|
25
|
+
cimdCache?: CimdCache;
|
|
26
|
+
cimdLookup?: (hostname: string) => Promise<string[]>;
|
|
27
|
+
}) => Pick<CimdFetchOptions, "cache" | "lookup">;
|
|
28
|
+
/** True when `client_id` is an HTTPS URL eligible for CIMD resolution. */
|
|
29
|
+
export declare const isCimdClientId: (clientId: string) => boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Fetch and validate a CIMD document for `clientId` (the HTTPS URL itself).
|
|
32
|
+
* Returns null on any validation / network failure — callers map that to
|
|
33
|
+
* `unauthorized_client` without leaking fetch details to the connector.
|
|
34
|
+
*/
|
|
35
|
+
export declare const resolveCimdClient: (clientId: string, options?: CimdFetchOptions) => Promise<CimdDocument | null>;
|
|
36
|
+
//# sourceMappingURL=cimd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimd.d.ts","sourceRoot":"","sources":["../../../src/oauth/cimd/cimd.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1D,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM1D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjD,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,aAAa,GAAI,OAAO;IACnC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACtD,KAAG,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,QAAQ,CAG3C,CAAC;AAEH,0EAA0E;AAC1E,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,KAAG,OAajD,CAAC;AAwGF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,UAAS,gBAAqB,KAC7B,OAAO,CAAC,YAAY,GAAG,IAAI,CAkB7B,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client ID Metadata Documents (CIMD) — HTTPS URL `client_id` metadata.
|
|
3
|
+
* Off by default (`cimd: true`). SSRF guards live in `cimd-ssrf.ts`.
|
|
4
|
+
*
|
|
5
|
+
* ponytail: DNS checked before/after fetch; TCP connect is not pinned (Web
|
|
6
|
+
* fetch). Upgrade: custom dispatcher dialing the resolved IP + Host header.
|
|
7
|
+
*/
|
|
8
|
+
import { readBoundedText } from "../../http/body.js";
|
|
9
|
+
import { parseCacheMaxAge, parseDocument } from "./cimd-parse.js";
|
|
10
|
+
import { assertSafeUrl, defaultLookup } from "./cimd-ssrf.js";
|
|
11
|
+
const CIMD_MAX_BYTES = 5 * 1024;
|
|
12
|
+
const CIMD_TIMEOUT_MS = 10_000;
|
|
13
|
+
const CIMD_MAX_REDIRECTS = 3;
|
|
14
|
+
/** Build fetch options from router/app CIMD ports. */
|
|
15
|
+
export const cimdFetchOpts = (ports) => ({
|
|
16
|
+
...(ports.cimdCache !== undefined ? { cache: ports.cimdCache } : {}),
|
|
17
|
+
...(ports.cimdLookup !== undefined ? { lookup: ports.cimdLookup } : {}),
|
|
18
|
+
});
|
|
19
|
+
/** True when `client_id` is an HTTPS URL eligible for CIMD resolution. */
|
|
20
|
+
export const isCimdClientId = (clientId) => {
|
|
21
|
+
try {
|
|
22
|
+
const url = new URL(clientId);
|
|
23
|
+
return (url.protocol === "https:" &&
|
|
24
|
+
url.username === "" &&
|
|
25
|
+
url.password === "" &&
|
|
26
|
+
url.hash === "" &&
|
|
27
|
+
Boolean(url.hostname));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const readCimdBody = async (ctx, response, current) => {
|
|
34
|
+
if (!response.ok)
|
|
35
|
+
return null;
|
|
36
|
+
// Stream-capped at CIMD_MAX_BYTES; signal cancels the locked reader on hop
|
|
37
|
+
// timeout (body.cancel() is a no-op while getReader() holds the lock).
|
|
38
|
+
try {
|
|
39
|
+
const text = await readBoundedText(response, CIMD_MAX_BYTES, ctx.signal);
|
|
40
|
+
// Re-check DNS after the body — see file-level ponytail on connect pinning.
|
|
41
|
+
await assertSafeUrl(current, ctx.lookup);
|
|
42
|
+
return {
|
|
43
|
+
doc: parseDocument(ctx.clientId, text),
|
|
44
|
+
maxAge: parseCacheMaxAge(response.headers.get("cache-control")),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const followRedirect = async (ctx, response, current) => {
|
|
52
|
+
const location = response.headers.get("location");
|
|
53
|
+
if (!location || ctx.redirect === CIMD_MAX_REDIRECTS)
|
|
54
|
+
return null;
|
|
55
|
+
const next = new URL(location, current);
|
|
56
|
+
// Same-origin only: a cross-origin hop would let an open redirect on a
|
|
57
|
+
// reputable host vouch for a document the attacker actually serves.
|
|
58
|
+
if (next.origin !== new URL(ctx.clientId).origin)
|
|
59
|
+
return null;
|
|
60
|
+
await assertSafeUrl(next, ctx.lookup);
|
|
61
|
+
return next;
|
|
62
|
+
};
|
|
63
|
+
const getCimdResponse = (fetchImpl, url, signal) => fetchImpl(url, {
|
|
64
|
+
method: "GET",
|
|
65
|
+
redirect: "manual",
|
|
66
|
+
signal,
|
|
67
|
+
headers: { Accept: "application/json" },
|
|
68
|
+
});
|
|
69
|
+
/** One request under its own timeout. */
|
|
70
|
+
const fetchHop = async (settings, current, redirect) => {
|
|
71
|
+
const controller = new AbortController();
|
|
72
|
+
const timer = setTimeout(() => controller.abort(), settings.timeoutMs);
|
|
73
|
+
const ctx = {
|
|
74
|
+
clientId: settings.clientId,
|
|
75
|
+
lookup: settings.lookup,
|
|
76
|
+
redirect,
|
|
77
|
+
signal: controller.signal,
|
|
78
|
+
};
|
|
79
|
+
try {
|
|
80
|
+
const response = await getCimdResponse(settings.fetch, current.toString(), controller.signal);
|
|
81
|
+
if (response.status >= 300 && response.status < 400) {
|
|
82
|
+
const next = await followRedirect(ctx, response, current);
|
|
83
|
+
return next ? { next } : { done: null };
|
|
84
|
+
}
|
|
85
|
+
// `await` keeps the body read inside this try — without it `finally`
|
|
86
|
+
// clears the timer as soon as headers arrive.
|
|
87
|
+
return { done: await readCimdBody(ctx, response, current) };
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
clearTimeout(timer);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const fetchCimdDocument = async (settings) => {
|
|
94
|
+
let current = new URL(settings.clientId);
|
|
95
|
+
await assertSafeUrl(current, settings.lookup);
|
|
96
|
+
for (let redirect = 0; redirect <= CIMD_MAX_REDIRECTS; redirect++) {
|
|
97
|
+
const hop = await fetchHop(settings, current, redirect);
|
|
98
|
+
if ("done" in hop)
|
|
99
|
+
return hop.done;
|
|
100
|
+
current = hop.next;
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Fetch and validate a CIMD document for `clientId` (the HTTPS URL itself).
|
|
106
|
+
* Returns null on any validation / network failure — callers map that to
|
|
107
|
+
* `unauthorized_client` without leaking fetch details to the connector.
|
|
108
|
+
*/
|
|
109
|
+
export const resolveCimdClient = async (clientId, options = {}) => {
|
|
110
|
+
if (!isCimdClientId(clientId))
|
|
111
|
+
return null;
|
|
112
|
+
const cached = options.cache ? await options.cache.get(clientId) : null;
|
|
113
|
+
if (cached)
|
|
114
|
+
return cached;
|
|
115
|
+
try {
|
|
116
|
+
const result = await fetchCimdDocument({
|
|
117
|
+
clientId,
|
|
118
|
+
fetch: options.fetch ?? globalThis.fetch,
|
|
119
|
+
lookup: options.lookup ?? defaultLookup,
|
|
120
|
+
timeoutMs: options.timeoutMs ?? CIMD_TIMEOUT_MS,
|
|
121
|
+
});
|
|
122
|
+
if (!result)
|
|
123
|
+
return null;
|
|
124
|
+
if (options.cache)
|
|
125
|
+
await options.cache.set(clientId, result.doc, result.maxAge);
|
|
126
|
+
return result.doc;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=cimd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cimd.js","sourceRoot":"","sources":["../../../src/oauth/cimd/cimd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** CIMD document and cache shapes, shared by the fetcher and the parser. */
|
|
2
|
+
export type CimdDocument = {
|
|
3
|
+
client_id: string;
|
|
4
|
+
redirect_uris: string[];
|
|
5
|
+
client_name?: string;
|
|
6
|
+
token_endpoint_auth_method?: string;
|
|
7
|
+
};
|
|
8
|
+
export type CimdCache = {
|
|
9
|
+
get: (clientId: string) => Promise<CimdDocument | null> | CimdDocument | null;
|
|
10
|
+
set: (clientId: string, doc: CimdDocument, maxAgeSeconds: number) => Promise<void> | void;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/oauth/cimd/types.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAE5E,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,YAAY,GAAG,IAAI,CAAC;IAC9E,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC3F,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/oauth/cimd/types.ts"],"names":[],"mappings":"AAAA,4EAA4E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** OAuth construction asserts and small response helpers. */
|
|
2
|
+
import type { MintedToken, OAuthPorts, OAuthRouterOptions } from "./types.js";
|
|
3
|
+
/** Default true — see `OAuthRouterOptions.allowUnregisteredClients`. */
|
|
4
|
+
export declare const unregisteredClientsAllowed: (options: OAuthRouterOptions) => boolean;
|
|
5
|
+
/** Default true since 1.0 — see `OAuthRouterOptions.requireRegisteredClients`. */
|
|
6
|
+
export declare const registeredClientsRequired: (options: OAuthRouterOptions) => boolean;
|
|
7
|
+
/** Scopes this AS advertises and is willing to grant. */
|
|
8
|
+
export declare const advertisedScopes: (options: OAuthRouterOptions) => string[];
|
|
9
|
+
/**
|
|
10
|
+
* Scopes granted when a client omits `scope`. Falls back to the full
|
|
11
|
+
* advertised set only when that set has at most one entry — see
|
|
12
|
+
* `assertScopeConfig`, which forbids the ambiguous multi-scope case at
|
|
13
|
+
* construction instead of silently over-granting here.
|
|
14
|
+
*/
|
|
15
|
+
export declare const defaultScopes: (options: OAuthRouterOptions) => string[];
|
|
16
|
+
/**
|
|
17
|
+
* A multi-scope server MUST say what an omitted `scope` grants — the
|
|
18
|
+
* alternative (silently granting everything advertised) is exactly the
|
|
19
|
+
* escalation least-privilege scoping exists to prevent.
|
|
20
|
+
*
|
|
21
|
+
* This controls only what a *token* is granted at authorize time —
|
|
22
|
+
* `defaultScopes: []` still leaves any tool that omits `ToolDef.scope`
|
|
23
|
+
* callable by a principal holding zero scopes, since that check happens
|
|
24
|
+
* per tool-call, not here. `createMcpApp` has the matching guard on the
|
|
25
|
+
* tool side: it refuses to construct with an unscoped tool once `scopes`
|
|
26
|
+
* has more than one entry (`assertToolScopesConfigured` in `app.ts`).
|
|
27
|
+
*/
|
|
28
|
+
export declare const assertScopeConfig: (options: OAuthRouterOptions) => void;
|
|
29
|
+
export declare const assertCodeSecret: (secret: string) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Resolves `codeSecret` to a non-empty key list — a single string becomes a
|
|
32
|
+
* one-element array. The **first** entry is the one every caller here uses
|
|
33
|
+
* to seal new material or hash new client secrets; the full array is what a
|
|
34
|
+
* caller trying to unseal/verify existing material tries in order (see
|
|
35
|
+
* `unsealAny`, `verifyClientSecretAny`). Every entry is validated the same
|
|
36
|
+
* way a lone string always was.
|
|
37
|
+
*/
|
|
38
|
+
export declare const resolveSecrets: (ports: OAuthPorts, request: Request) => Promise<readonly [string, ...string[]]>;
|
|
39
|
+
export declare const oauthError: (error: string, status: number, description?: string) => Response;
|
|
40
|
+
/** Direct JSON error when this AS does not serve unknown `client_id`s. */
|
|
41
|
+
export declare const unregisteredClientError: (options: OAuthRouterOptions, reject: {
|
|
42
|
+
code: string;
|
|
43
|
+
status: number;
|
|
44
|
+
}) => Response | null;
|
|
45
|
+
/**
|
|
46
|
+
* `grantedScope` is what the auth code carried (or a narrowed refresh
|
|
47
|
+
* request); the port may narrow it further. With neither, `scope` is
|
|
48
|
+
* omitted (optional when unchanged, RFC 6749 §5.1) rather than guessed.
|
|
49
|
+
*/
|
|
50
|
+
export declare const tokenResponse: (minted: MintedToken, grantedScope?: string) => Response;
|
|
51
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/oauth/config.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAI7D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE9E,wEAAwE;AACxE,eAAO,MAAM,0BAA0B,GAAI,SAAS,kBAAkB,KAAG,OAC7B,CAAC;AAE7C,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,GAAI,SAAS,kBAAkB,KAAG,OAC5B,CAAC;AAE7C,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,GAAI,SAAS,kBAAkB,KAAG,MAAM,EAClC,CAAC;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,kBAAkB,KAAG,MAAM,EACd,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,kBAAkB,KAAG,IAY/D,CAAC;AAaF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,IAYjD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GACzB,OAAO,UAAU,EACjB,SAAS,OAAO,KACf,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAUxC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,EAAE,cAAc,MAAM,KAAG,QAK7E,CAAC;AAKL,0EAA0E;AAC1E,eAAO,MAAM,uBAAuB,GAClC,SAAS,kBAAkB,EAC3B,QAAQ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KACvC,QAAQ,GAAG,IAGb,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,WAAW,EAAE,eAAe,MAAM,KAAG,QAa1E,CAAC"}
|