mcp-trellis 0.2.1 → 2.1.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 +70 -620
- 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 +16 -24
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +69 -88
- 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 -66
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +150 -57
- 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 +25 -5
- package/dist/auth/bearer.js.map +1 -1
- package/dist/clients.d.ts.map +1 -1
- package/dist/clients.js +3 -6
- 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/http/body.d.ts +69 -0
- package/dist/http/body.d.ts.map +1 -0
- package/dist/http/body.js +165 -0
- 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/mcp/dispatch.d.ts +7 -0
- 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} +10 -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/mcp/methods.d.ts +133 -0
- 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/mcp/protocol.d.ts +16 -0
- package/dist/mcp/protocol.d.ts.map +1 -0
- package/dist/mcp/protocol.js +22 -0
- 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} +30 -2
- 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} +24 -12
- package/dist/mcp/validate.d.ts.map +1 -0
- package/dist/mcp/validate.js +186 -0
- 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 +15 -0
- package/dist/oauth/constants.d.ts.map +1 -1
- package/dist/oauth/constants.js +15 -0
- package/dist/oauth/constants.js.map +1 -1
- package/dist/oauth/{base64url.d.ts → crypto/base64url.d.ts} +1 -2
- package/dist/oauth/crypto/base64url.d.ts.map +1 -0
- package/dist/oauth/{base64url.js → crypto/base64url.js} +1 -5
- 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/crypto/sealed.d.ts +26 -0
- package/dist/oauth/crypto/sealed.d.ts.map +1 -0
- package/dist/oauth/crypto/sealed.js +65 -0
- package/dist/oauth/crypto/sealed.js.map +1 -0
- package/dist/oauth/crypto/secrethash.d.ts +58 -0
- package/dist/oauth/crypto/secrethash.d.ts.map +1 -0
- package/dist/oauth/crypto/secrethash.js +82 -0
- 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} +14 -8
- 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} +11 -9
- 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} +33 -47
- 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 -7
- package/dist/oauth/endpoints/wellknown.js.map +1 -0
- package/dist/oauth/{redirect.d.ts → policy/redirect.d.ts} +6 -1
- package/dist/oauth/policy/redirect.d.ts.map +1 -0
- package/dist/oauth/policy/redirect.js +39 -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/policy/resource.d.ts +37 -0
- package/dist/oauth/policy/resource.d.ts.map +1 -0
- package/dist/oauth/policy/resource.js +74 -0
- package/dist/oauth/policy/resource.js.map +1 -0
- package/dist/oauth/policy/scope.d.ts +20 -0
- package/dist/oauth/policy/scope.d.ts.map +1 -0
- package/dist/oauth/policy/scope.js +35 -0
- package/dist/oauth/policy/scope.js.map +1 -0
- package/dist/oauth/router.d.ts +12 -12
- package/dist/oauth/router.d.ts.map +1 -1
- package/dist/oauth/router.js +105 -87
- package/dist/oauth/router.js.map +1 -1
- package/dist/oauth/types.d.ts +177 -26
- package/dist/oauth/types.d.ts.map +1 -1
- package/dist/oauth/types.js +1 -27
- package/dist/oauth/types.js.map +1 -1
- package/dist/server.d.ts +14 -13
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -9
- 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 +283 -0
- package/docs/compatibility.md +84 -0
- package/docs/diagrams/mcp-trellis-architecture.html +305 -0
- package/docs/guide.md +441 -0
- package/docs/reference.md +210 -0
- package/docs/security.md +112 -0
- package/docs/troubleshooting.md +19 -0
- package/package.json +24 -8
- package/dist/adapters/origins.d.ts +0 -19
- package/dist/adapters/origins.d.ts.map +0 -1
- package/dist/adapters/origins.js +0 -55
- package/dist/adapters/origins.js.map +0 -1
- package/dist/dispatch.d.ts +0 -7
- package/dist/dispatch.d.ts.map +0 -1
- package/dist/dispatch.js +0 -79
- 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 -17
- package/dist/jsonrpc.js.map +0 -1
- package/dist/methods.d.ts +0 -61
- package/dist/methods.d.ts.map +0 -1
- package/dist/methods.js +0 -114
- 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 -109
- 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 -19
- package/dist/oauth/clientauth.d.ts.map +0 -1
- package/dist/oauth/clientauth.js +0 -76
- 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 -93
- package/dist/oauth/codes.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 +0 -26
- package/dist/oauth/redirect.js.map +0 -1
- package/dist/oauth/resource.d.ts +0 -7
- package/dist/oauth/resource.d.ts.map +0 -1
- package/dist/oauth/resource.js +0 -44
- 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 +0 -11
- package/dist/oauth/scope.d.ts.map +0 -1
- package/dist/oauth/scope.js +0 -24
- package/dist/oauth/scope.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 +0 -4
- package/dist/protocol.d.ts.map +0 -1
- package/dist/protocol.js +0 -14
- 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 -69
- package/dist/registry.js.map +0 -1
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -97
- package/dist/tools.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js +0 -130
- package/dist/validate.js.map +0 -1
- /package/dist/oauth/{pkce.d.ts → crypto/pkce.d.ts} +0 -0
|
@@ -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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/** OAuth construction asserts and small response helpers. */
|
|
2
|
+
import { jsonResponse } from "../http/http.js";
|
|
3
|
+
import { DEFAULT_SCOPE } from "./constants.js";
|
|
4
|
+
/** Default true — see `OAuthRouterOptions.allowUnregisteredClients`. */
|
|
5
|
+
export const unregisteredClientsAllowed = (options) => options.allowUnregisteredClients !== false;
|
|
6
|
+
/** Default true since 1.0 — see `OAuthRouterOptions.requireRegisteredClients`. */
|
|
7
|
+
export const registeredClientsRequired = (options) => options.requireRegisteredClients !== false;
|
|
8
|
+
/** Scopes this AS advertises and is willing to grant. */
|
|
9
|
+
export const advertisedScopes = (options) => options.scopes ?? [DEFAULT_SCOPE];
|
|
10
|
+
/**
|
|
11
|
+
* Scopes granted when a client omits `scope`. Falls back to the full
|
|
12
|
+
* advertised set only when that set has at most one entry — see
|
|
13
|
+
* `assertScopeConfig`, which forbids the ambiguous multi-scope case at
|
|
14
|
+
* construction instead of silently over-granting here.
|
|
15
|
+
*/
|
|
16
|
+
export const defaultScopes = (options) => options.defaultScopes ?? advertisedScopes(options);
|
|
17
|
+
/**
|
|
18
|
+
* A multi-scope server MUST say what an omitted `scope` grants — the
|
|
19
|
+
* alternative (silently granting everything advertised) is exactly the
|
|
20
|
+
* escalation least-privilege scoping exists to prevent.
|
|
21
|
+
*
|
|
22
|
+
* This controls only what a *token* is granted at authorize time —
|
|
23
|
+
* `defaultScopes: []` still leaves any tool that omits `ToolDef.scope`
|
|
24
|
+
* callable by a principal holding zero scopes, since that check happens
|
|
25
|
+
* per tool-call, not here. `createMcpApp` has the matching guard on the
|
|
26
|
+
* tool side: it refuses to construct with an unscoped tool once `scopes`
|
|
27
|
+
* has more than one entry (`assertToolScopesConfigured` in `app.ts`).
|
|
28
|
+
*/
|
|
29
|
+
export const assertScopeConfig = (options) => {
|
|
30
|
+
const advertised = advertisedScopes(options);
|
|
31
|
+
if (advertised.length > 1 && !options.defaultScopes) {
|
|
32
|
+
throw new Error("scopes has more than one entry — defaultScopes must say what an omitted " +
|
|
33
|
+
"scope request grants (e.g. defaultScopes: [] for least privilege)");
|
|
34
|
+
}
|
|
35
|
+
const unknown = (options.defaultScopes ?? []).find((scope) => !advertised.includes(scope));
|
|
36
|
+
if (unknown !== undefined) {
|
|
37
|
+
throw new Error(`defaultScopes contains "${unknown}", which is not in scopes`);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* `codeSecret` can forge an auth code for any userId/scope/resource, so a
|
|
42
|
+
* weak or copy-pasted one is a full authorization bypass, not a footgun.
|
|
43
|
+
* Copy-paste from this package's docs is the realistic failure mode: every
|
|
44
|
+
* published example secret is either under the length floor or carries
|
|
45
|
+
* the marker below (enforced by test/oauth/crypto/codesecret.test.ts).
|
|
46
|
+
*/
|
|
47
|
+
const MIN_CODE_SECRET_LENGTH = 32;
|
|
48
|
+
const DENYLISTED_CODE_SECRET_MARKER = "do-not-reuse";
|
|
49
|
+
const GENERATE_HINT = "generate one with `openssl rand -base64 32`";
|
|
50
|
+
export const assertCodeSecret = (secret) => {
|
|
51
|
+
// Checked before the length rule so a copied example is named for what it is.
|
|
52
|
+
if (secret.includes(DENYLISTED_CODE_SECRET_MARKER)) {
|
|
53
|
+
throw new Error(`codeSecret must not be a literal published in this package's own docs or examples — ${GENERATE_HINT}`);
|
|
54
|
+
}
|
|
55
|
+
if (secret.length < MIN_CODE_SECRET_LENGTH) {
|
|
56
|
+
throw new Error(`codeSecret must be at least ${MIN_CODE_SECRET_LENGTH} characters (got ${secret.length}) — ${GENERATE_HINT}`);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Resolves `codeSecret` to a non-empty key list — a single string becomes a
|
|
61
|
+
* one-element array. The **first** entry is the one every caller here uses
|
|
62
|
+
* to seal new material or hash new client secrets; the full array is what a
|
|
63
|
+
* caller trying to unseal/verify existing material tries in order (see
|
|
64
|
+
* `unsealAny`, `verifyClientSecretAny`). Every entry is validated the same
|
|
65
|
+
* way a lone string always was.
|
|
66
|
+
*/
|
|
67
|
+
export const resolveSecrets = async (ports, request) => {
|
|
68
|
+
const resolved = typeof ports.codeSecret === "function" ? await ports.codeSecret(request) : ports.codeSecret;
|
|
69
|
+
const secrets = Array.isArray(resolved) ? resolved : [resolved];
|
|
70
|
+
if (secrets.length === 0) {
|
|
71
|
+
throw new Error("codeSecret must resolve to at least one key, not an empty array");
|
|
72
|
+
}
|
|
73
|
+
secrets.forEach(assertCodeSecret);
|
|
74
|
+
// Cast is sound: the length check above guarantees at least one element.
|
|
75
|
+
return secrets;
|
|
76
|
+
};
|
|
77
|
+
export const oauthError = (error, status, description) => jsonResponse({
|
|
78
|
+
data: description ? { error, error_description: description } : { error },
|
|
79
|
+
status,
|
|
80
|
+
cors: false,
|
|
81
|
+
});
|
|
82
|
+
const UNREGISTERED_CLIENT_DESCRIPTION = "unknown client_id — this server only serves pre-registered clients";
|
|
83
|
+
/** Direct JSON error when this AS does not serve unknown `client_id`s. */
|
|
84
|
+
export const unregisteredClientError = (options, reject) => {
|
|
85
|
+
if (unregisteredClientsAllowed(options))
|
|
86
|
+
return null;
|
|
87
|
+
return oauthError(reject.code, reject.status, UNREGISTERED_CLIENT_DESCRIPTION);
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* `grantedScope` is what the auth code carried (or a narrowed refresh
|
|
91
|
+
* request); the port may narrow it further. With neither, `scope` is
|
|
92
|
+
* omitted (optional when unchanged, RFC 6749 §5.1) rather than guessed.
|
|
93
|
+
*/
|
|
94
|
+
export const tokenResponse = (minted, grantedScope) => {
|
|
95
|
+
const scope = minted.scope ?? grantedScope;
|
|
96
|
+
return jsonResponse({
|
|
97
|
+
data: {
|
|
98
|
+
access_token: minted.accessToken,
|
|
99
|
+
token_type: minted.tokenType ?? "bearer",
|
|
100
|
+
expires_in: minted.expiresIn,
|
|
101
|
+
...(scope !== undefined ? { scope } : {}),
|
|
102
|
+
...(minted.refreshToken ? { refresh_token: minted.refreshToken } : {}),
|
|
103
|
+
},
|
|
104
|
+
status: 200,
|
|
105
|
+
cors: false,
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/oauth/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,16 +8,22 @@ export declare const OAUTH_ERRORS: {
|
|
|
8
8
|
readonly invalidGrant: "invalid_grant";
|
|
9
9
|
readonly unsupportedGrantType: "unsupported_grant_type";
|
|
10
10
|
readonly invalidRedirectUri: "invalid_redirect_uri";
|
|
11
|
+
/** RFC 7591 §3.2.2 — DCR `/register`: a client metadata field's value itself is invalid. */
|
|
12
|
+
readonly invalidClientMetadata: "invalid_client_metadata";
|
|
11
13
|
/** Token endpoint — client authentication failed, or the client is unknown. */
|
|
12
14
|
readonly invalidClient: "invalid_client";
|
|
13
15
|
/** Authorization endpoint — this client may not use this method. RFC 6749 §4.1.2.1. */
|
|
14
16
|
readonly unauthorizedClient: "unauthorized_client";
|
|
17
|
+
/** Authorization endpoint — `response_type` isn't one this server supports. RFC 6749 §4.1.2.1. */
|
|
18
|
+
readonly unsupportedResponseType: "unsupported_response_type";
|
|
15
19
|
/** Requested scope exceeds what this server advertises. */
|
|
16
20
|
readonly invalidScope: "invalid_scope";
|
|
17
21
|
/** RFC 8707 — requested resource is not acceptable. */
|
|
18
22
|
readonly invalidTarget: "invalid_target";
|
|
19
23
|
/** A host port threw. RFC 6749 §4.1.2.1 / §5.2 — our fault, not the client's. */
|
|
20
24
|
readonly serverError: "server_error";
|
|
25
|
+
/** RFC 6749 §4.1.2.1 — the resource owner denied consent. */
|
|
26
|
+
readonly accessDenied: "access_denied";
|
|
21
27
|
};
|
|
22
28
|
export declare const TOKEN_ENDPOINT_AUTH_METHODS: {
|
|
23
29
|
/** Public client — PKCE is the only proof. */
|
|
@@ -29,4 +35,13 @@ export declare const TOKEN_ENDPOINT_AUTH_METHODS: {
|
|
|
29
35
|
};
|
|
30
36
|
export type TokenEndpointAuthMethod = (typeof TOKEN_ENDPOINT_AUTH_METHODS)[keyof typeof TOKEN_ENDPOINT_AUTH_METHODS];
|
|
31
37
|
export declare const DEFAULT_SCOPE = "mcp";
|
|
38
|
+
/** Default OAuth path prefix when `oauthPath` is unset. Router, `/authorize`, and metadata must agree. */
|
|
39
|
+
export declare const DEFAULT_OAUTH_PATH = "/mcp/oauth";
|
|
40
|
+
/**
|
|
41
|
+
* Cap on a client's redirect URIs, self-registered or from a CIMD document.
|
|
42
|
+
* RFC 7591 sets none, but `/register` seals the whole list into the
|
|
43
|
+
* `client_id`, which then travels as an `/authorize` query parameter with
|
|
44
|
+
* real length ceilings (browsers, proxies, logs). A client needs a handful.
|
|
45
|
+
*/
|
|
46
|
+
export declare const MAX_CLIENT_REDIRECT_URIS = 10;
|
|
32
47
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/oauth/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEvE,eAAO,MAAM,YAAY;;;;;IAKvB,+EAA+E;;IAE/E,uFAAuF;;IAEvF,2DAA2D;;IAE3D,uDAAuD;;IAEvD,iFAAiF;;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/oauth/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEvE,eAAO,MAAM,YAAY;;;;;IAKvB,4FAA4F;;IAE5F,+EAA+E;;IAE/E,uFAAuF;;IAEvF,kGAAkG;;IAElG,2DAA2D;;IAE3D,uDAAuD;;IAEvD,iFAAiF;;IAEjF,6DAA6D;;CAErD,CAAC;AAEX,eAAO,MAAM,2BAA2B;IACtC,8CAA8C;;IAE9C,+CAA+C;;IAE/C,uCAAuC;;CAE/B,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,OAAO,2BAA2B,CAAC,CAAC;AAEjF,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,0GAA0G;AAC1G,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,KAAK,CAAC"}
|
package/dist/oauth/constants.js
CHANGED
|
@@ -7,16 +7,22 @@ export const OAUTH_ERRORS = {
|
|
|
7
7
|
invalidGrant: "invalid_grant",
|
|
8
8
|
unsupportedGrantType: "unsupported_grant_type",
|
|
9
9
|
invalidRedirectUri: "invalid_redirect_uri",
|
|
10
|
+
/** RFC 7591 §3.2.2 — DCR `/register`: a client metadata field's value itself is invalid. */
|
|
11
|
+
invalidClientMetadata: "invalid_client_metadata",
|
|
10
12
|
/** Token endpoint — client authentication failed, or the client is unknown. */
|
|
11
13
|
invalidClient: "invalid_client",
|
|
12
14
|
/** Authorization endpoint — this client may not use this method. RFC 6749 §4.1.2.1. */
|
|
13
15
|
unauthorizedClient: "unauthorized_client",
|
|
16
|
+
/** Authorization endpoint — `response_type` isn't one this server supports. RFC 6749 §4.1.2.1. */
|
|
17
|
+
unsupportedResponseType: "unsupported_response_type",
|
|
14
18
|
/** Requested scope exceeds what this server advertises. */
|
|
15
19
|
invalidScope: "invalid_scope",
|
|
16
20
|
/** RFC 8707 — requested resource is not acceptable. */
|
|
17
21
|
invalidTarget: "invalid_target",
|
|
18
22
|
/** A host port threw. RFC 6749 §4.1.2.1 / §5.2 — our fault, not the client's. */
|
|
19
23
|
serverError: "server_error",
|
|
24
|
+
/** RFC 6749 §4.1.2.1 — the resource owner denied consent. */
|
|
25
|
+
accessDenied: "access_denied",
|
|
20
26
|
};
|
|
21
27
|
export const TOKEN_ENDPOINT_AUTH_METHODS = {
|
|
22
28
|
/** Public client — PKCE is the only proof. */
|
|
@@ -27,4 +33,13 @@ export const TOKEN_ENDPOINT_AUTH_METHODS = {
|
|
|
27
33
|
post: "client_secret_post",
|
|
28
34
|
};
|
|
29
35
|
export const DEFAULT_SCOPE = "mcp";
|
|
36
|
+
/** Default OAuth path prefix when `oauthPath` is unset. Router, `/authorize`, and metadata must agree. */
|
|
37
|
+
export const DEFAULT_OAUTH_PATH = "/mcp/oauth";
|
|
38
|
+
/**
|
|
39
|
+
* Cap on a client's redirect URIs, self-registered or from a CIMD document.
|
|
40
|
+
* RFC 7591 sets none, but `/register` seals the whole list into the
|
|
41
|
+
* `client_id`, which then travels as an `/authorize` query parameter with
|
|
42
|
+
* real length ceilings (browsers, proxies, logs). A client needs a handful.
|
|
43
|
+
*/
|
|
44
|
+
export const MAX_CLIENT_REDIRECT_URIS = 10;
|
|
30
45
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/oauth/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,iBAAiB,EAAE,oBAAoB;IACvC,YAAY,EAAE,eAAe;CACrB,CAAC;AAIX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,cAAc,EAAE,iBAAiB;IACjC,YAAY,EAAE,eAAe;IAC7B,oBAAoB,EAAE,wBAAwB;IAC9C,kBAAkB,EAAE,sBAAsB;IAC1C,+EAA+E;IAC/E,aAAa,EAAE,gBAAgB;IAC/B,uFAAuF;IACvF,kBAAkB,EAAE,qBAAqB;IACzC,2DAA2D;IAC3D,YAAY,EAAE,eAAe;IAC7B,uDAAuD;IACvD,aAAa,EAAE,gBAAgB;IAC/B,iFAAiF;IACjF,WAAW,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/oauth/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,iBAAiB,EAAE,oBAAoB;IACvC,YAAY,EAAE,eAAe;CACrB,CAAC;AAIX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,cAAc,EAAE,iBAAiB;IACjC,YAAY,EAAE,eAAe;IAC7B,oBAAoB,EAAE,wBAAwB;IAC9C,kBAAkB,EAAE,sBAAsB;IAC1C,4FAA4F;IAC5F,qBAAqB,EAAE,yBAAyB;IAChD,+EAA+E;IAC/E,aAAa,EAAE,gBAAgB;IAC/B,uFAAuF;IACvF,kBAAkB,EAAE,qBAAqB;IACzC,kGAAkG;IAClG,uBAAuB,EAAE,2BAA2B;IACpD,2DAA2D;IAC3D,YAAY,EAAE,eAAe;IAC7B,uDAAuD;IACvD,aAAa,EAAE,gBAAgB;IAC/B,iFAAiF;IACjF,WAAW,EAAE,cAAc;IAC3B,6DAA6D;IAC7D,YAAY,EAAE,eAAe;CACrB,CAAC;AAEX,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,8CAA8C;IAC9C,IAAI,EAAE,MAAM;IACZ,+CAA+C;IAC/C,KAAK,EAAE,qBAAqB;IAC5B,uCAAuC;IACvC,IAAI,EAAE,oBAAoB;CAClB,CAAC;AAKX,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC;AAEnC,0GAA0G;AAC1G,MAAM,CAAC,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/** Shared base64url helpers (WebCrypto / DOM — no Node Buffer). */
|
|
2
2
|
export declare const bytesToBase64Url: (bytes: ArrayBuffer | Uint8Array) => string;
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const fromBase64Url: (text: string) => Uint8Array;
|
|
3
|
+
export declare const fromBase64Url: (text: string) => Uint8Array<ArrayBuffer>;
|
|
5
4
|
//# sourceMappingURL=base64url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64url.d.ts","sourceRoot":"","sources":["../../../src/oauth/crypto/base64url.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,eAAO,MAAM,gBAAgB,GAAI,OAAO,WAAW,GAAG,UAAU,KAAG,MAIlE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,UAAU,CAAC,WAAW,CAKlE,CAAC"}
|
|
@@ -2,12 +2,8 @@
|
|
|
2
2
|
export const bytesToBase64Url = (bytes) => {
|
|
3
3
|
const u8 = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
4
4
|
const binary = Array.from(u8, (byte) => String.fromCharCode(byte)).join("");
|
|
5
|
-
return btoa(binary)
|
|
6
|
-
.replace(/\+/g, "-")
|
|
7
|
-
.replace(/\//g, "_")
|
|
8
|
-
.replace(/=+$/, "");
|
|
5
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
9
6
|
};
|
|
10
|
-
export const textToBase64Url = (text) => bytesToBase64Url(new TextEncoder().encode(text));
|
|
11
7
|
export const fromBase64Url = (text) => {
|
|
12
8
|
const padded = text.replace(/-/g, "+").replace(/_/g, "/");
|
|
13
9
|
const pad = padded.length % 4 === 0 ? "" : "=".repeat(4 - (padded.length % 4));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64url.js","sourceRoot":"","sources":["../../../src/oauth/crypto/base64url.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAA+B,EAAU,EAAE;IAC1E,MAAM,EAAE,GAAG,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACjF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAA2B,EAAE;IACrE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IAC/B,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Token-endpoint client authentication (RFC 6749 §2.3.1). */
|
|
2
|
+
import { type TokenEndpointAuthMethod } from "../constants.js";
|
|
3
|
+
import type { OAuthRouterOptions } from "../types.js";
|
|
4
|
+
export type ClientAuth = {
|
|
5
|
+
clientId: string;
|
|
6
|
+
secret: string | null;
|
|
7
|
+
method: TokenEndpointAuthMethod;
|
|
8
|
+
};
|
|
9
|
+
/** Credentials from the Authorization header, else from the body. */
|
|
10
|
+
export declare const readClientAuth: (request: Request, body: Record<string, string>) => ClientAuth | null;
|
|
11
|
+
/** Enforce the registered auth method for known clients — see the helpers above for each branch. */
|
|
12
|
+
export declare const firstClientAuthError: (auth: ClientAuth, options: OAuthRouterOptions, request: Request) => Promise<Response | null>;
|
|
13
|
+
//# sourceMappingURL=clientauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientauth.d.ts","sourceRoot":"","sources":["../../../src/oauth/crypto/clientauth.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAU9D,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAGV,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAIrB,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,uBAAuB,CAAC;CACjC,CAAC;AA6BF,qEAAqE;AACrE,eAAO,MAAM,cAAc,GACzB,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC3B,UAAU,GAAG,IAaf,CAAC;AA2LF,oGAAoG;AACpG,eAAO,MAAM,oBAAoB,GAC/B,MAAM,UAAU,EAChB,SAAS,kBAAkB,EAC3B,SAAS,OAAO,KACf,OAAO,CAAC,QAAQ,GAAG,IAAI,CAMzB,CAAC"}
|