mindweave 2.4.4 → 2.4.6
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/dist/cli/App.js +158 -99
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/attachments.js +14 -1
- package/dist/cli/attachments.js.map +1 -1
- package/dist/cli/components/KeyManager.js +3 -42
- package/dist/cli/components/KeyManager.js.map +1 -1
- package/dist/cli/components/McpMinitabs.js +689 -0
- package/dist/cli/components/McpMinitabs.js.map +1 -0
- package/dist/cli/components/minitabs.js +71 -0
- package/dist/cli/components/minitabs.js.map +1 -0
- package/dist/dynamo/engine.js +29 -7
- package/dist/dynamo/engine.js.map +1 -1
- package/dist/dynamo/prompt.js +2 -0
- package/dist/dynamo/prompt.js.map +1 -1
- package/dist/mcp/config.js +57 -3
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/configWrite.js +40 -2
- package/dist/mcp/configWrite.js.map +1 -1
- package/dist/mcp/connection.js +51 -1
- package/dist/mcp/connection.js.map +1 -1
- package/dist/mcp/manager.js +65 -0
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/oauth/callback.js +171 -0
- package/dist/mcp/oauth/callback.js.map +1 -0
- package/dist/mcp/oauth/flow.js +415 -0
- package/dist/mcp/oauth/flow.js.map +1 -0
- package/dist/mcp/oauth/index.js +243 -0
- package/dist/mcp/oauth/index.js.map +1 -0
- package/dist/mcp/oauth/metadata.js +192 -0
- package/dist/mcp/oauth/metadata.js.map +1 -0
- package/dist/mcp/oauth/pkce.js +56 -0
- package/dist/mcp/oauth/pkce.js.map +1 -0
- package/dist/mcp/oauth/tokenStore.js +103 -0
- package/dist/mcp/oauth/tokenStore.js.map +1 -0
- package/dist/mcp/transport/http.js +33 -5
- package/dist/mcp/transport/http.js.map +1 -1
- package/dist/memory/session.js +4 -0
- package/dist/memory/session.js.map +1 -1
- package/dist/tools/backgroundShells.js +42 -4
- package/dist/tools/backgroundShells.js.map +1 -1
- package/dist/tools/mcpAdd.js +7 -0
- package/dist/tools/mcpAdd.js.map +1 -1
- package/dist/tools/subagent.js +41 -3
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/todo.js +35 -0
- package/dist/tools/todo.js.map +1 -1
- package/dist/tools/verifyReport.js +144 -0
- package/dist/tools/verifyReport.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback.js","sourceRoot":"","sources":["../../../src/mcp/oauth/callback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,aAAa,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACjD,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAC/C,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB;;4EAE4E;AAC5E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,MAAM,CAAC;AAE9C,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,wFAAwF;IACxF,wFAAwF;IACxF,iFAAiF;IACjF,uFAAuF;IACvF,uFAAuF;IACvF,mDAAmD;IACnD,EAAE;IACF,yFAAyF;IACzF,sFAAsF;IACtF,EAAE;IACF,uFAAuF;IACvF,oFAAoF;IACpF,OAAO,oBAAoB,IAAI,WAAW,CAAC;AAC7C,CAAC;AAED,SAAS,SAAS,CAAC,WAA4B,OAAO,CAAC,QAAQ;IAC7D,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;AAC5D,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,WAA4B,OAAO,CAAC,QAAQ;IAClF,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/E,IAAI,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IAEtE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACzC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,aAAa,EAAE,OAAO,EAAE,EAAE,CAAC;QACzD,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/D,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACtC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1C,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC;AAgBD;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,OAAoB;IAClD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,GAAG,mBAAmB,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACzE,OAAO,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrD,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,MAAM,MAAM,GAAG,CAAC,EAAc,EAAQ,EAAE;YACtC,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,+EAA+E;YAC/E,+EAA+E;YAC/E,KAAK,MAAM,CAAC,IAAI,OAAO;gBAAE,CAAC,CAAC,KAAK,EAAE,CAAC;YACnC,EAAE,EAAE,CAAC;QACP,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAC7H,qFAAqF;QACrF,kFAAkF;QAClF,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAEhB,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC;QACxF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAE3D,MAAM,MAAM,GAAG,CAAC,GAAoB,EAAE,GAAmB,EAAQ,EAAE;YACjE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,IAAI,EAAE,CAAC,CAAC;YAChE,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACjC,8EAA8E;gBAC9E,2BAA2B;gBAC3B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBACzB,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAE/C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAC9D,OAAO,CAAC,GAAG,EAAE,6BAA6B,EAAE,oDAAoD,CAAC,CAAC;gBAClG,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAClF,OAAO;YACT,CAAC;YACD,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,EAAE,6BAA6B,EAAE,gDAAgD,CAAC,CAAC;gBAC9F,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC,CAAC,CAAC;gBACtG,OAAO;YACT,CAAC;YACD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,EAAE,kCAAkC,EAAE,+BAA+B,CAAC,CAAC;gBAClF,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC,CAAC,CAAC;gBAC9E,OAAO;YACT,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,oDAAoD,CAAC,CAAC;YACjF,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAClC,CAAC,CAAC;QAEF,uFAAuF;QACvF,uFAAuF;QACvF,sFAAsF;QACtF,sFAAsF;QACtF,qFAAqF;QACrF,iCAAiC;QACjC,EAAE;QACF,oFAAoF;QACpF,gDAAgD;QAChD,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,QAAiB,EAAQ,EAAE;YACzD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;gBAClD,IAAI,CAAC,QAAQ;oBAAE,OAAO,CAAC,kDAAkD;gBACzE,MAAM,MAAM,GACV,GAAG,CAAC,IAAI,KAAK,YAAY;oBACvB,CAAC,CAAC,cAAc,IAAI,wDAAwD;oBAC5E,CAAC,CAAC,sCAAsC,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC1D,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1C,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC1B,iFAAiF;YACjF,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;QACnB,CAAC,CAAC;QACF,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAEvB,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;wEAEwE;AACxE,SAAS,OAAO,CAAC,GAAmB,EAAE,KAAa,EAAE,MAAc;IACjE,MAAM,IAAI,GAAG,+CAA+C,KAAK;;gCAEnC,KAAK,WAAW,MAAM,aAAa,CAAC;IAClE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* flow.ts — the network half of authorization: ask who issues tokens, get a client id,
|
|
3
|
+
* send the user to approve, redeem the code, and refresh it later.
|
|
4
|
+
*
|
|
5
|
+
* `metadata.ts` decides WHAT to fetch and how to read the answers; this file does the
|
|
6
|
+
* fetching and the four POSTs. Split that way because the branching is all in the
|
|
7
|
+
* parsing, and a test that has to stand up an HTTP server to check a fallback ordering is
|
|
8
|
+
* a test nobody keeps working.
|
|
9
|
+
*
|
|
10
|
+
* ONE RULE RUNS THROUGH ALL OF IT: every step reports the sentence a user can act on. An
|
|
11
|
+
* authorization failure is not a stack trace and is very rarely OUR bug — it is a
|
|
12
|
+
* consent screen that was declined, a server without dynamic registration, a token that
|
|
13
|
+
* was revoked in a dashboard an hour ago. The error strings here are the product.
|
|
14
|
+
*/
|
|
15
|
+
import { authServerUrls, protectedResourceUrls, readAuthServerMetadata, readResourceMetadata, supportsS256, } from "./metadata.js";
|
|
16
|
+
/** How long any single metadata or token request may take. Generous rather than snappy:
|
|
17
|
+
* an authorization server is very often a cold serverless function, and a discovery that
|
|
18
|
+
* gives up at five seconds fails for a reason that has nothing to do with the user. */
|
|
19
|
+
const REQUEST_TIMEOUT_MS = 30_000;
|
|
20
|
+
export class TokenRequestError extends Error {
|
|
21
|
+
kind;
|
|
22
|
+
constructor(message, kind) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.kind = kind;
|
|
25
|
+
this.name = "TokenRequestError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Error codes that MEAN `invalid_grant` without saying it.
|
|
30
|
+
*
|
|
31
|
+
* Not pedantry: at least one widely used provider answers a dead refresh token with its
|
|
32
|
+
* own vocabulary, and treating that as an unknown failure means never clearing a
|
|
33
|
+
* credential that will never work again — the user sits in a silent retry loop instead of
|
|
34
|
+
* being offered the sign-in that would fix it.
|
|
35
|
+
*/
|
|
36
|
+
const INVALID_GRANT_ALIASES = new Set(["invalid_refresh_token", "expired_refresh_token", "token_expired"]);
|
|
37
|
+
/** Statuses worth trying again. 408/429 and the 5xx family are the server saying "not
|
|
38
|
+
* now" rather than "no". */
|
|
39
|
+
function transientStatus(status) {
|
|
40
|
+
return status === 408 || status === 429 || status >= 500;
|
|
41
|
+
}
|
|
42
|
+
/** A thrown error that is the network rather than the server: a timeout, a reset, a DNS
|
|
43
|
+
* failure. All of them are "try again", none of them say anything about the credential. */
|
|
44
|
+
export function isTransientNetworkError(error) {
|
|
45
|
+
if (error instanceof TokenRequestError)
|
|
46
|
+
return error.kind === "transient";
|
|
47
|
+
const message = String(error?.message ?? error).toLowerCase();
|
|
48
|
+
return /timeout|timed out|etimedout|econnreset|econnrefused|enotfound|eai_again|socket hang up|network|fetch failed|aborted/.test(message);
|
|
49
|
+
}
|
|
50
|
+
/** What the client calls itself when it registers. Not a brand exercise: an
|
|
51
|
+
* authorization server shows this string on the consent screen and in the user's list of
|
|
52
|
+
* connected applications, so it has to say which program is asking. */
|
|
53
|
+
const CLIENT_NAME = "Mindweave";
|
|
54
|
+
async function getJson(url, fetchImpl) {
|
|
55
|
+
const controller = new AbortController();
|
|
56
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
57
|
+
timer.unref?.();
|
|
58
|
+
try {
|
|
59
|
+
const response = await fetchImpl(url, { headers: { accept: "application/json" }, signal: controller.signal });
|
|
60
|
+
if (!response.ok)
|
|
61
|
+
return null;
|
|
62
|
+
return (await response.json());
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// A candidate URL that 404s, times out or is not JSON is not an error, it is a
|
|
66
|
+
// candidate that was wrong — the caller has more to try.
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
clearTimeout(timer);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Walk the chain: the 401's metadata URL (or the well-known guesses) to the resource
|
|
75
|
+
* document, the resource document to its authorization servers, and each of those to its
|
|
76
|
+
* own metadata.
|
|
77
|
+
*
|
|
78
|
+
* FALLS THROUGH TO THE SERVER ITSELF when there is no resource document anywhere. A great
|
|
79
|
+
* many deployed servers are their own authorization server and publish RFC 8414 metadata
|
|
80
|
+
* directly, having never implemented the newer RFC 9728 layer at all, and refusing those
|
|
81
|
+
* would be refusing a large part of the ecosystem to honour a document nobody promised.
|
|
82
|
+
*/
|
|
83
|
+
export async function discover(serverUrl, challenge, fetchImpl = fetch,
|
|
84
|
+
/** A metadata document named in the config, for a server that publishes none of the
|
|
85
|
+
* discovery documents. Tried alone: if someone went to the trouble of naming it, a
|
|
86
|
+
* silent fallback to guessing would hide the fact that it was wrong. */
|
|
87
|
+
configuredMetadataUrl) {
|
|
88
|
+
if (configuredMetadataUrl) {
|
|
89
|
+
const meta = readAuthServerMetadata(await getJson(configuredMetadataUrl, fetchImpl));
|
|
90
|
+
if (!meta)
|
|
91
|
+
throw new Error(`no usable OAuth metadata at the configured authServerMetadataUrl (${configuredMetadataUrl})`);
|
|
92
|
+
if (!supportsS256(meta))
|
|
93
|
+
throw new Error(`${configuredMetadataUrl} does not offer PKCE with S256, which is required to sign in safely`);
|
|
94
|
+
return { authServer: meta, resource: null };
|
|
95
|
+
}
|
|
96
|
+
const resourceCandidates = challenge.resourceMetadata
|
|
97
|
+
? [challenge.resourceMetadata, ...protectedResourceUrls(serverUrl)]
|
|
98
|
+
: protectedResourceUrls(serverUrl);
|
|
99
|
+
let resource = null;
|
|
100
|
+
for (const candidate of resourceCandidates) {
|
|
101
|
+
const parsed = readResourceMetadata(await getJson(candidate, fetchImpl));
|
|
102
|
+
if (parsed) {
|
|
103
|
+
resource = parsed;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const issuers = resource ? resource.authorizationServers : [new URL(serverUrl).origin, serverUrl];
|
|
108
|
+
for (const issuer of issuers) {
|
|
109
|
+
for (const candidate of authServerUrls(issuer)) {
|
|
110
|
+
const meta = readAuthServerMetadata(await getJson(candidate, fetchImpl));
|
|
111
|
+
if (!meta)
|
|
112
|
+
continue;
|
|
113
|
+
if (!supportsS256(meta)) {
|
|
114
|
+
throw new Error(`${issuer} does not offer PKCE with S256, which is required to sign in safely`);
|
|
115
|
+
}
|
|
116
|
+
return { authServer: meta, resource };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
throw new Error(resource
|
|
120
|
+
? `this server names an authorization server (${issuers[0] ?? "unknown"}) that publishes no usable OAuth metadata`
|
|
121
|
+
: "this server asked for authorization but publishes no OAuth metadata, so there is nothing to sign in to");
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Register as a new client (RFC 7591), because a CLI has no client id until it asks for
|
|
125
|
+
* one and there is nowhere to type one in.
|
|
126
|
+
*
|
|
127
|
+
* An authorization server with no registration endpoint is a genuine wall, and the error
|
|
128
|
+
* says so plainly rather than implying a retry would help: that server expects a client
|
|
129
|
+
* id created by hand in its dashboard, which is a different feature and a different
|
|
130
|
+
* conversation.
|
|
131
|
+
*/
|
|
132
|
+
export async function registerClient(meta, redirect, fetchImpl = fetch) {
|
|
133
|
+
if (!meta.registrationEndpoint) {
|
|
134
|
+
throw new Error("this authorization server does not support automatic client registration");
|
|
135
|
+
}
|
|
136
|
+
const response = await fetchImpl(meta.registrationEndpoint, {
|
|
137
|
+
method: "POST",
|
|
138
|
+
headers: { "content-type": "application/json", accept: "application/json" },
|
|
139
|
+
body: JSON.stringify({
|
|
140
|
+
client_name: CLIENT_NAME,
|
|
141
|
+
redirect_uris: [redirect],
|
|
142
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
143
|
+
response_types: ["code"],
|
|
144
|
+
// A public client: see pkce.ts for why a CLI cannot hold a secret. Servers that
|
|
145
|
+
// issue one anyway are handled — we store it — but we do not claim to be able to
|
|
146
|
+
// keep it.
|
|
147
|
+
token_endpoint_auth_method: "none",
|
|
148
|
+
application_type: "native",
|
|
149
|
+
}),
|
|
150
|
+
});
|
|
151
|
+
if (!response.ok) {
|
|
152
|
+
throw new Error(`could not register with the authorization server (${response.status}): ${await errorText(response)}`);
|
|
153
|
+
}
|
|
154
|
+
const body = (await response.json());
|
|
155
|
+
const clientId = typeof body.client_id === "string" ? body.client_id : "";
|
|
156
|
+
if (!clientId)
|
|
157
|
+
throw new Error("the authorization server registered us but issued no client id");
|
|
158
|
+
const out = { clientId };
|
|
159
|
+
if (typeof body.client_secret === "string" && body.client_secret)
|
|
160
|
+
out.clientSecret = body.client_secret;
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
/** The URL to open in the browser (pure). */
|
|
164
|
+
export function authorizeUrl(options) {
|
|
165
|
+
const url = new URL(options.meta.authorizationEndpoint);
|
|
166
|
+
url.searchParams.set("response_type", "code");
|
|
167
|
+
url.searchParams.set("client_id", options.clientId);
|
|
168
|
+
url.searchParams.set("redirect_uri", options.redirect);
|
|
169
|
+
url.searchParams.set("code_challenge", options.pkce.challenge);
|
|
170
|
+
url.searchParams.set("code_challenge_method", options.pkce.method);
|
|
171
|
+
url.searchParams.set("state", options.state);
|
|
172
|
+
if (options.scope)
|
|
173
|
+
url.searchParams.set("scope", options.scope);
|
|
174
|
+
if (options.resource)
|
|
175
|
+
url.searchParams.set("resource", options.resource);
|
|
176
|
+
return url.toString();
|
|
177
|
+
}
|
|
178
|
+
async function postToken(endpoint, form, fetchImpl, signal) {
|
|
179
|
+
const controller = new AbortController();
|
|
180
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
181
|
+
timer.unref?.();
|
|
182
|
+
const onAbort = () => controller.abort();
|
|
183
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
184
|
+
if (signal?.aborted)
|
|
185
|
+
controller.abort();
|
|
186
|
+
let response;
|
|
187
|
+
let raw;
|
|
188
|
+
try {
|
|
189
|
+
response = await fetchImpl(endpoint, {
|
|
190
|
+
method: "POST",
|
|
191
|
+
headers: { "content-type": "application/x-www-form-urlencoded", accept: "application/json" },
|
|
192
|
+
body: form.toString(),
|
|
193
|
+
signal: controller.signal,
|
|
194
|
+
});
|
|
195
|
+
raw = await response.text();
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
// Never reached the server, or did not finish. Says nothing about the credential.
|
|
199
|
+
throw new TokenRequestError(`could not reach the authorization server: ${String(error?.message ?? error)}`, "transient");
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
clearTimeout(timer);
|
|
203
|
+
signal?.removeEventListener("abort", onAbort);
|
|
204
|
+
}
|
|
205
|
+
let body = {};
|
|
206
|
+
try {
|
|
207
|
+
body = JSON.parse(raw);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Not JSON. Only meaningful if the status already said no.
|
|
211
|
+
}
|
|
212
|
+
// AN ERROR CAN ARRIVE WITH A 200. At least one widely used provider answers every
|
|
213
|
+
// request with 200 and puts the failure in the body, so status alone is not the test —
|
|
214
|
+
// a body carrying `error` is an error whatever the status line claims.
|
|
215
|
+
const declared = typeof body.error === "string" ? body.error : "";
|
|
216
|
+
if (!response.ok || declared) {
|
|
217
|
+
const code = INVALID_GRANT_ALIASES.has(declared) ? "invalid_grant" : declared;
|
|
218
|
+
const description = typeof body.error_description === "string" ? body.error_description : "";
|
|
219
|
+
const kind = code === "invalid_grant" ? "invalid_grant" : transientStatus(response.status) ? "transient" : "other";
|
|
220
|
+
const detail = [code, description].filter(Boolean).join(": ") || clip(raw) || response.statusText || "no detail";
|
|
221
|
+
throw new TokenRequestError(`the authorization server refused the request (${response.status}): ${detail}`, kind);
|
|
222
|
+
}
|
|
223
|
+
const accessToken = typeof body.access_token === "string" ? body.access_token : "";
|
|
224
|
+
if (!accessToken)
|
|
225
|
+
throw new TokenRequestError("the authorization server returned no access token", "other");
|
|
226
|
+
const out = { accessToken };
|
|
227
|
+
if (typeof body.refresh_token === "string" && body.refresh_token)
|
|
228
|
+
out.refreshToken = body.refresh_token;
|
|
229
|
+
if (typeof body.scope === "string" && body.scope)
|
|
230
|
+
out.scope = body.scope;
|
|
231
|
+
// `expires_in` is seconds from now. Converted to an absolute moment here because that
|
|
232
|
+
// is what survives being written to a file and read back tomorrow.
|
|
233
|
+
if (typeof body.expires_in === "number" && Number.isFinite(body.expires_in)) {
|
|
234
|
+
out.expiresAt = Date.now() + body.expires_in * 1000;
|
|
235
|
+
}
|
|
236
|
+
else if (out.refreshToken) {
|
|
237
|
+
// The server did not say, but gave us a way to renew. An hour is the near-universal
|
|
238
|
+
// default, and assuming it means we refresh QUIETLY on schedule rather than finding
|
|
239
|
+
// out through a 401 that sends the user back to a browser. Without a refresh token
|
|
240
|
+
// the guess would buy nothing, so it is not made: see `isExpired`.
|
|
241
|
+
out.expiresAt = Date.now() + 3_600_000;
|
|
242
|
+
}
|
|
243
|
+
return out;
|
|
244
|
+
}
|
|
245
|
+
/** Redeem the authorization code for tokens. */
|
|
246
|
+
export async function exchangeCode(options, fetchImpl = fetch) {
|
|
247
|
+
const form = new URLSearchParams({
|
|
248
|
+
grant_type: "authorization_code",
|
|
249
|
+
code: options.code,
|
|
250
|
+
redirect_uri: options.redirect,
|
|
251
|
+
client_id: options.clientId,
|
|
252
|
+
code_verifier: options.verifier,
|
|
253
|
+
});
|
|
254
|
+
if (options.clientSecret)
|
|
255
|
+
form.set("client_secret", options.clientSecret);
|
|
256
|
+
if (options.resource)
|
|
257
|
+
form.set("resource", options.resource);
|
|
258
|
+
return postToken(options.meta.tokenEndpoint, form, fetchImpl);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Trade a refresh token for a new access token.
|
|
262
|
+
*
|
|
263
|
+
* The refresh token is CARRIED FORWARD when the server does not send a new one: many
|
|
264
|
+
* rotate them and many do not, and dropping the old one on a server that does not would
|
|
265
|
+
* sign the user out an hour later for no reason.
|
|
266
|
+
*/
|
|
267
|
+
export async function refreshTokens(options, fetchImpl = fetch) {
|
|
268
|
+
const form = new URLSearchParams({
|
|
269
|
+
grant_type: "refresh_token",
|
|
270
|
+
refresh_token: options.refreshToken,
|
|
271
|
+
client_id: options.clientId,
|
|
272
|
+
});
|
|
273
|
+
if (options.clientSecret)
|
|
274
|
+
form.set("client_secret", options.clientSecret);
|
|
275
|
+
if (options.resource)
|
|
276
|
+
form.set("resource", options.resource);
|
|
277
|
+
// RETRIED, unlike the code exchange. A refresh happens on its own, without anyone
|
|
278
|
+
// watching, against a server that may be briefly rate limiting or restarting — and the
|
|
279
|
+
// cost of giving up early is not a slow request, it is a credential thrown away and a
|
|
280
|
+
// browser round trip the user has to notice. The code exchange is not retried because
|
|
281
|
+
// an authorization code is single-use: a second attempt with the same code is refused
|
|
282
|
+
// by definition, and the user is right there and can simply try again.
|
|
283
|
+
let last;
|
|
284
|
+
for (let attempt = 1; attempt <= REFRESH_ATTEMPTS; attempt++) {
|
|
285
|
+
try {
|
|
286
|
+
const tokens = await postToken(options.tokenEndpoint, form, fetchImpl);
|
|
287
|
+
// Carried forward when the server sends no new one: many rotate refresh tokens and
|
|
288
|
+
// many do not, and dropping the old one on a server that does not would sign the
|
|
289
|
+
// user out an hour later for no reason.
|
|
290
|
+
if (!tokens.refreshToken)
|
|
291
|
+
tokens.refreshToken = options.refreshToken;
|
|
292
|
+
return tokens;
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
last = error;
|
|
296
|
+
const retryable = error instanceof TokenRequestError ? error.kind === "transient" : isTransientNetworkError(error);
|
|
297
|
+
if (!retryable || attempt === REFRESH_ATTEMPTS)
|
|
298
|
+
throw error;
|
|
299
|
+
await sleep(REFRESH_BACKOFF_MS * 2 ** (attempt - 1));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
throw last;
|
|
303
|
+
}
|
|
304
|
+
/** A millisecond value with an env override, for testing the backoff without spending it
|
|
305
|
+
* for real. Same pattern the background-shell stall watchdog uses. Unset or invalid falls
|
|
306
|
+
* back to the default. */
|
|
307
|
+
function envMs(name, fallback) {
|
|
308
|
+
const raw = Number(process.env[name]);
|
|
309
|
+
return Number.isFinite(raw) && raw >= 0 ? raw : fallback;
|
|
310
|
+
}
|
|
311
|
+
/** Three tries at 1s and 2s apart. Enough to ride out a restart or a rate limit, short
|
|
312
|
+
* enough that a genuinely dead server does not hold a request for a minute. */
|
|
313
|
+
const REFRESH_ATTEMPTS = 3;
|
|
314
|
+
const REFRESH_BACKOFF_MS = envMs("MINDWEAVE_OAUTH_BACKOFF_MS", 1_000);
|
|
315
|
+
/**
|
|
316
|
+
* NOT unref'd, and that is the whole point of this comment.
|
|
317
|
+
*
|
|
318
|
+
* Every other timer in this feature is unref'd so a forgotten sign-in cannot hold the
|
|
319
|
+
* process open. This one is the opposite case: it sits inside an AWAITED retry, so the
|
|
320
|
+
* sleep IS the pending work. Unref'ing it lets Node decide the loop has nothing left to
|
|
321
|
+
* do, exit it, and leave the await unsettled forever — a refresh that silently never
|
|
322
|
+
* resumes rather than one that fails. CI caught it as "Promise resolution is still
|
|
323
|
+
* pending but the event loop has already resolved"; it reproduces in four lines of plain
|
|
324
|
+
* Node with no test runner involved.
|
|
325
|
+
*/
|
|
326
|
+
function sleep(ms) {
|
|
327
|
+
return new Promise((resolve) => {
|
|
328
|
+
setTimeout(resolve, ms);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Tell the authorization server a token is finished with (RFC 7009).
|
|
333
|
+
*
|
|
334
|
+
* BEST EFFORT, and deliberately so: signing out has already succeeded locally by the time
|
|
335
|
+
* this runs, and a server that does not implement revocation, or is simply down, must not
|
|
336
|
+
* turn "signed out" into an error. What this buys is that a token we stop using also
|
|
337
|
+
* stops WORKING, rather than remaining valid on the server until it expires.
|
|
338
|
+
*
|
|
339
|
+
* The client id goes in the BODY rather than an Authorization header, which is what RFC
|
|
340
|
+
* 7009 asks of a public client: the header is for the resource owner, not for identifying
|
|
341
|
+
* which client is revoking.
|
|
342
|
+
*/
|
|
343
|
+
export async function revokeToken(options, fetchImpl = fetch) {
|
|
344
|
+
const post = async (form, headers) => {
|
|
345
|
+
const controller = new AbortController();
|
|
346
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
347
|
+
timer.unref?.();
|
|
348
|
+
try {
|
|
349
|
+
return await fetchImpl(options.revocationEndpoint, {
|
|
350
|
+
method: "POST",
|
|
351
|
+
headers: { "content-type": "application/x-www-form-urlencoded", ...headers },
|
|
352
|
+
body: form.toString(),
|
|
353
|
+
signal: controller.signal,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
return null; // best effort — see above
|
|
358
|
+
}
|
|
359
|
+
finally {
|
|
360
|
+
clearTimeout(timer);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
const form = new URLSearchParams({ token: options.token, token_type_hint: options.hint });
|
|
364
|
+
// RFC 7009 §2.1 wants client authentication, and WHICH form matters. A client holding a
|
|
365
|
+
// secret is confidential, and strict authorization servers refuse a confidential
|
|
366
|
+
// client's token being revoked by something presenting as public — so a secret goes as
|
|
367
|
+
// HTTP Basic, the default RFC 6749 §2.3.1 form, rather than in the body. A public client
|
|
368
|
+
// identifies itself with `client_id` in the body and nothing else.
|
|
369
|
+
const headers = {};
|
|
370
|
+
if (options.clientSecret) {
|
|
371
|
+
const basic = Buffer.from(`${encodeURIComponent(options.clientId)}:${encodeURIComponent(options.clientSecret)}`).toString("base64");
|
|
372
|
+
headers.authorization = `Basic ${basic}`;
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
form.set("client_id", options.clientId);
|
|
376
|
+
}
|
|
377
|
+
const response = await post(form, headers);
|
|
378
|
+
if (!response || response.ok || response.status !== 401)
|
|
379
|
+
return;
|
|
380
|
+
// Some servers are not RFC 7009 compliant and want the access token as a Bearer instead.
|
|
381
|
+
// RFC 6749 §2.3.1 forbids presenting two client authentication methods at once, so the
|
|
382
|
+
// body credential is dropped before switching.
|
|
383
|
+
if (!options.accessToken)
|
|
384
|
+
return;
|
|
385
|
+
const retry = new URLSearchParams({ token: options.token, token_type_hint: options.hint });
|
|
386
|
+
await post(retry, { authorization: `Bearer ${options.accessToken}` });
|
|
387
|
+
}
|
|
388
|
+
/** An OAuth error body names `error` and `error_description`; anything else is shown
|
|
389
|
+
* as-is, clipped, because an HTML error page in a terminal helps nobody. */
|
|
390
|
+
async function errorText(response) {
|
|
391
|
+
let raw = "";
|
|
392
|
+
try {
|
|
393
|
+
raw = await response.text();
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
return response.statusText || "no detail";
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
const body = JSON.parse(raw);
|
|
400
|
+
const error = typeof body.error === "string" ? body.error : "";
|
|
401
|
+
const description = typeof body.error_description === "string" ? body.error_description : "";
|
|
402
|
+
if (error || description)
|
|
403
|
+
return [error, description].filter(Boolean).join(": ");
|
|
404
|
+
}
|
|
405
|
+
catch {
|
|
406
|
+
// Not JSON; fall through to the clipped body.
|
|
407
|
+
}
|
|
408
|
+
return clip(raw) || response.statusText || "no detail";
|
|
409
|
+
}
|
|
410
|
+
/** One line, bounded. A wall of HTML in a terminal helps nobody. */
|
|
411
|
+
function clip(raw) {
|
|
412
|
+
const flat = raw.replace(/\s+/g, " ").trim();
|
|
413
|
+
return flat.length > 200 ? `${flat.slice(0, 199)}…` : flat;
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../../src/mcp/oauth/flow.ts"],"names":[],"mappings":"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"}
|