@sonoma-security/mcp-gateway 0.1.11 → 0.1.13
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/__tests__/plugin-discovery.test.d.ts +12 -0
- package/dist/__tests__/plugin-discovery.test.d.ts.map +1 -0
- package/dist/__tests__/plugin-discovery.test.js +367 -0
- package/dist/__tests__/plugin-discovery.test.js.map +1 -0
- package/dist/__tests__/tool-blocking.test.d.ts +2 -0
- package/dist/__tests__/tool-blocking.test.d.ts.map +1 -0
- package/dist/__tests__/tool-blocking.test.js +256 -0
- package/dist/__tests__/tool-blocking.test.js.map +1 -0
- package/dist/auth/client.d.ts.map +1 -1
- package/dist/auth/client.js +49 -6
- package/dist/auth/client.js.map +1 -1
- package/dist/auth/keychain.d.ts +34 -0
- package/dist/auth/keychain.d.ts.map +1 -0
- package/dist/auth/keychain.js +305 -0
- package/dist/auth/keychain.js.map +1 -0
- package/dist/auth/server.d.ts +15 -3
- package/dist/auth/server.d.ts.map +1 -1
- package/dist/auth/server.js +110 -23
- package/dist/auth/server.js.map +1 -1
- package/dist/auth/storage.d.ts +5 -6
- package/dist/auth/storage.d.ts.map +1 -1
- package/dist/auth/storage.js +72 -21
- package/dist/auth/storage.js.map +1 -1
- package/dist/auth/upstream-oauth.d.ts +2 -0
- package/dist/auth/upstream-oauth.d.ts.map +1 -1
- package/dist/auth/upstream-oauth.js +58 -8
- package/dist/auth/upstream-oauth.js.map +1 -1
- package/dist/auth/upstream-token-store.d.ts +18 -6
- package/dist/auth/upstream-token-store.d.ts.map +1 -1
- package/dist/auth/upstream-token-store.js +127 -35
- package/dist/auth/upstream-token-store.js.map +1 -1
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -7
- package/dist/config.js.map +1 -1
- package/dist/gateway.d.ts +17 -0
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +302 -66
- package/dist/gateway.js.map +1 -1
- package/dist/http-proxy.d.ts +76 -0
- package/dist/http-proxy.d.ts.map +1 -0
- package/dist/http-proxy.js +316 -0
- package/dist/http-proxy.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/pattern-matcher.d.ts +25 -0
- package/dist/pattern-matcher.d.ts.map +1 -1
- package/dist/pattern-matcher.js +65 -0
- package/dist/pattern-matcher.js.map +1 -1
- package/dist/prompt-guard.d.ts +24 -0
- package/dist/prompt-guard.d.ts.map +1 -0
- package/dist/prompt-guard.js +161 -0
- package/dist/prompt-guard.js.map +1 -0
- package/dist/sonoma-client.d.ts +28 -1
- package/dist/sonoma-client.d.ts.map +1 -1
- package/dist/sonoma-client.js +67 -43
- package/dist/sonoma-client.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OS Keychain abstraction for secure credential storage.
|
|
3
|
+
*
|
|
4
|
+
* Uses native OS credential stores via CLI tools (no native modules needed):
|
|
5
|
+
* - macOS: Keychain Access via `security` CLI
|
|
6
|
+
* - Windows: Credential Manager via PowerShell
|
|
7
|
+
* - Linux/other: Falls back to encrypted file storage (existing behavior)
|
|
8
|
+
*
|
|
9
|
+
* All credentials are stored as JSON strings, keyed by (service, account).
|
|
10
|
+
*/
|
|
11
|
+
import { execSync } from "node:child_process";
|
|
12
|
+
const SERVICE_NAME = "sonoma-mcp-gateway";
|
|
13
|
+
/**
|
|
14
|
+
* Store a credential in the OS keychain.
|
|
15
|
+
* @param account - Unique key within the service (e.g., "sonoma-auth", "upstream:https://mcp.slack.com")
|
|
16
|
+
* @param data - Credential data (will be JSON-stringified)
|
|
17
|
+
*/
|
|
18
|
+
export function keychainSet(account, data) {
|
|
19
|
+
const json = JSON.stringify(data);
|
|
20
|
+
const platform = process.platform;
|
|
21
|
+
if (platform === "darwin") {
|
|
22
|
+
macosSet(account, json);
|
|
23
|
+
}
|
|
24
|
+
else if (platform === "win32") {
|
|
25
|
+
windowsSet(account, json);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
throw new Error(`Keychain not supported on ${platform}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Retrieve a credential from the OS keychain.
|
|
33
|
+
* @returns Parsed JSON data, or null if not found
|
|
34
|
+
*/
|
|
35
|
+
export function keychainGet(account) {
|
|
36
|
+
const platform = process.platform;
|
|
37
|
+
let json;
|
|
38
|
+
if (platform === "darwin") {
|
|
39
|
+
json = macosGet(account);
|
|
40
|
+
}
|
|
41
|
+
else if (platform === "win32") {
|
|
42
|
+
json = windowsGet(account);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
throw new Error(`Keychain not supported on ${platform}`);
|
|
46
|
+
}
|
|
47
|
+
if (json === null)
|
|
48
|
+
return null;
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(json);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Delete a credential from the OS keychain.
|
|
58
|
+
*/
|
|
59
|
+
export function keychainDelete(account) {
|
|
60
|
+
const platform = process.platform;
|
|
61
|
+
if (platform === "darwin") {
|
|
62
|
+
macosDelete(account);
|
|
63
|
+
}
|
|
64
|
+
else if (platform === "win32") {
|
|
65
|
+
windowsDelete(account);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
throw new Error(`Keychain not supported on ${platform}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Delete all credentials for the service from the OS keychain.
|
|
73
|
+
*/
|
|
74
|
+
export function keychainDeleteAll() {
|
|
75
|
+
const platform = process.platform;
|
|
76
|
+
if (platform === "darwin") {
|
|
77
|
+
macosDeleteAll();
|
|
78
|
+
}
|
|
79
|
+
else if (platform === "win32") {
|
|
80
|
+
windowsDeleteAll();
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
throw new Error(`Keychain not supported on ${platform}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check whether OS keychain is available on this platform.
|
|
88
|
+
*/
|
|
89
|
+
export function keychainAvailable() {
|
|
90
|
+
const platform = process.platform;
|
|
91
|
+
if (platform === "darwin" || platform === "win32") {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// macOS Keychain via `security` CLI
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
function macosSet(account, password) {
|
|
100
|
+
// -U = update if exists, -s = service, -a = account, -w = password
|
|
101
|
+
// Accepted risk: macOS `security` CLI requires -w <password> as a CLI argument,
|
|
102
|
+
// which briefly exposes it in the process list. There is no stdin alternative for
|
|
103
|
+
// add-generic-password. The exposure window is sub-second and local-only.
|
|
104
|
+
execSync(`/usr/bin/security add-generic-password -s ${shellEscape(SERVICE_NAME)} -a ${shellEscape(account)} -U -w ${shellEscape(password)}`, { stdio: "pipe" });
|
|
105
|
+
}
|
|
106
|
+
function macosGet(account) {
|
|
107
|
+
try {
|
|
108
|
+
const result = execSync(`/usr/bin/security find-generic-password -s ${shellEscape(SERVICE_NAME)} -a ${shellEscape(account)} -w`, { stdio: "pipe", encoding: "utf-8" });
|
|
109
|
+
return result.trim();
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Not found (exit code 44) or other error
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function macosDelete(account) {
|
|
117
|
+
try {
|
|
118
|
+
execSync(`/usr/bin/security delete-generic-password -s ${shellEscape(SERVICE_NAME)} -a ${shellEscape(account)}`, { stdio: "pipe" });
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Ignore if not found
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function macosDeleteAll() {
|
|
125
|
+
// Delete entries one at a time until none remain
|
|
126
|
+
for (let i = 0; i < 100; i++) {
|
|
127
|
+
try {
|
|
128
|
+
execSync(`/usr/bin/security delete-generic-password -s ${shellEscape(SERVICE_NAME)}`, { stdio: "pipe" });
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
break; // No more entries
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
// Windows Credential Manager via PowerShell
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
function windowsTargetName(account) {
|
|
139
|
+
return `${SERVICE_NAME}:${account}`;
|
|
140
|
+
}
|
|
141
|
+
function windowsSet(account, password) {
|
|
142
|
+
const target = windowsTargetName(account);
|
|
143
|
+
// Use CredWrite via .NET interop for arbitrary credential storage.
|
|
144
|
+
// Base64-encode the password to avoid escaping issues in PowerShell.
|
|
145
|
+
const b64 = Buffer.from(password, "utf-8").toString("base64");
|
|
146
|
+
const ps = `
|
|
147
|
+
$ErrorActionPreference='Stop'
|
|
148
|
+
Add-Type -TypeDefinition @"
|
|
149
|
+
using System;
|
|
150
|
+
using System.Runtime.InteropServices;
|
|
151
|
+
using System.Text;
|
|
152
|
+
|
|
153
|
+
public class CredManager {
|
|
154
|
+
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
155
|
+
public static extern bool CredWriteW(ref CREDENTIAL cred, uint flags);
|
|
156
|
+
[DllImport("advapi32.dll", SetLastError=true)]
|
|
157
|
+
public static extern bool CredFree(IntPtr buffer);
|
|
158
|
+
|
|
159
|
+
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
|
|
160
|
+
public struct CREDENTIAL {
|
|
161
|
+
public uint Flags;
|
|
162
|
+
public uint Type;
|
|
163
|
+
public string TargetName;
|
|
164
|
+
public string Comment;
|
|
165
|
+
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
|
|
166
|
+
public uint CredentialBlobSize;
|
|
167
|
+
public IntPtr CredentialBlob;
|
|
168
|
+
public uint Persist;
|
|
169
|
+
public uint AttributeCount;
|
|
170
|
+
public IntPtr Attributes;
|
|
171
|
+
public string TargetAlias;
|
|
172
|
+
public string UserName;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public static void Write(string target, string secret) {
|
|
176
|
+
byte[] bytes = Encoding.UTF8.GetBytes(secret);
|
|
177
|
+
IntPtr blob = Marshal.AllocHGlobal(bytes.Length);
|
|
178
|
+
Marshal.Copy(bytes, 0, blob, bytes.Length);
|
|
179
|
+
CREDENTIAL cred = new CREDENTIAL();
|
|
180
|
+
cred.Type = 1; // CRED_TYPE_GENERIC
|
|
181
|
+
cred.TargetName = target;
|
|
182
|
+
cred.CredentialBlobSize = (uint)bytes.Length;
|
|
183
|
+
cred.CredentialBlob = blob;
|
|
184
|
+
cred.Persist = 2; // CRED_PERSIST_LOCAL_MACHINE
|
|
185
|
+
cred.UserName = "sonoma-gateway";
|
|
186
|
+
bool ok = CredWriteW(ref cred, 0);
|
|
187
|
+
Marshal.FreeHGlobal(blob);
|
|
188
|
+
if (!ok) throw new Exception("CredWrite failed: " + Marshal.GetLastWin32Error());
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
"@
|
|
192
|
+
$targetB64 = '${Buffer.from(target, "utf-8").toString("base64")}'
|
|
193
|
+
$target = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($targetB64))
|
|
194
|
+
$secret = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}'))
|
|
195
|
+
[CredManager]::Write($target, $secret)
|
|
196
|
+
`;
|
|
197
|
+
execSync(`powershell -NoProfile -NonInteractive -Command "${ps.replace(/"/g, '\\"')}"`, {
|
|
198
|
+
stdio: "pipe",
|
|
199
|
+
windowsHide: true,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function windowsGet(account) {
|
|
203
|
+
const target = windowsTargetName(account);
|
|
204
|
+
const ps = `
|
|
205
|
+
$ErrorActionPreference='Stop'
|
|
206
|
+
Add-Type -TypeDefinition @"
|
|
207
|
+
using System;
|
|
208
|
+
using System.Runtime.InteropServices;
|
|
209
|
+
using System.Text;
|
|
210
|
+
|
|
211
|
+
public class CredReader {
|
|
212
|
+
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
213
|
+
public static extern bool CredReadW(string target, uint type, uint flags, out IntPtr cred);
|
|
214
|
+
[DllImport("advapi32.dll", SetLastError=true)]
|
|
215
|
+
public static extern bool CredFree(IntPtr buffer);
|
|
216
|
+
|
|
217
|
+
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
|
|
218
|
+
public struct CREDENTIAL {
|
|
219
|
+
public uint Flags;
|
|
220
|
+
public uint Type;
|
|
221
|
+
public string TargetName;
|
|
222
|
+
public string Comment;
|
|
223
|
+
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
|
|
224
|
+
public uint CredentialBlobSize;
|
|
225
|
+
public IntPtr CredentialBlob;
|
|
226
|
+
public uint Persist;
|
|
227
|
+
public uint AttributeCount;
|
|
228
|
+
public IntPtr Attributes;
|
|
229
|
+
public string TargetAlias;
|
|
230
|
+
public string UserName;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public static string Read(string target) {
|
|
234
|
+
IntPtr credPtr;
|
|
235
|
+
bool ok = CredReadW(target, 1, 0, out credPtr);
|
|
236
|
+
if (!ok) return null;
|
|
237
|
+
CREDENTIAL cred = (CREDENTIAL)Marshal.PtrToStructure(credPtr, typeof(CREDENTIAL));
|
|
238
|
+
byte[] bytes = new byte[cred.CredentialBlobSize];
|
|
239
|
+
Marshal.Copy(cred.CredentialBlob, bytes, 0, bytes.Length);
|
|
240
|
+
CredFree(credPtr);
|
|
241
|
+
return Encoding.UTF8.GetString(bytes);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
"@
|
|
245
|
+
$targetB64 = '${Buffer.from(target, "utf-8").toString("base64")}'
|
|
246
|
+
$t = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($targetB64))
|
|
247
|
+
$result = [CredReader]::Read($t)
|
|
248
|
+
if ($result -eq $null) { exit 1 }
|
|
249
|
+
[Console]::Write($result)
|
|
250
|
+
`;
|
|
251
|
+
try {
|
|
252
|
+
return execSync(`powershell -NoProfile -NonInteractive -Command "${ps.replace(/"/g, '\\"')}"`, { stdio: "pipe", encoding: "utf-8", windowsHide: true });
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function windowsDelete(account) {
|
|
259
|
+
const target = windowsTargetName(account);
|
|
260
|
+
try {
|
|
261
|
+
execSync(`cmdkey /delete:${target}`, { stdio: "pipe", windowsHide: true });
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Ignore if not found
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function windowsDeleteAll() {
|
|
268
|
+
// List all credentials matching our service prefix and delete them
|
|
269
|
+
try {
|
|
270
|
+
const output = execSync("cmdkey /list", {
|
|
271
|
+
stdio: "pipe",
|
|
272
|
+
encoding: "utf-8",
|
|
273
|
+
windowsHide: true,
|
|
274
|
+
});
|
|
275
|
+
const prefix = `${SERVICE_NAME}:`;
|
|
276
|
+
for (const line of output.split("\n")) {
|
|
277
|
+
const match = line.match(/Target:\s*(.+)/i);
|
|
278
|
+
if (match) {
|
|
279
|
+
const target = match[1].trim();
|
|
280
|
+
if (target.startsWith(prefix)) {
|
|
281
|
+
try {
|
|
282
|
+
execSync(`cmdkey /delete:${target}`, { stdio: "pipe", windowsHide: true });
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
// Ignore individual delete failures
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// Ignore errors
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
// Helpers
|
|
297
|
+
// ---------------------------------------------------------------------------
|
|
298
|
+
/**
|
|
299
|
+
* Shell-escape a string for use in a command argument.
|
|
300
|
+
* Wraps in single quotes and escapes embedded single quotes.
|
|
301
|
+
*/
|
|
302
|
+
function shellEscape(s) {
|
|
303
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=keychain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../src/auth/keychain.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/server.d.ts
CHANGED
|
@@ -15,12 +15,24 @@ export interface CallbackServerOptions {
|
|
|
15
15
|
/** Name of the service being authenticated (shown on success page) */
|
|
16
16
|
serverName?: string;
|
|
17
17
|
}
|
|
18
|
+
export interface CallbackServerHandle {
|
|
19
|
+
/** Promise that resolves with the authorization code when received */
|
|
20
|
+
waitForCallback: () => Promise<CallbackResult>;
|
|
21
|
+
/** Clean up the server without waiting for a callback */
|
|
22
|
+
close: () => void;
|
|
23
|
+
/** Set the auth URL so the timeout page can offer a retry button */
|
|
24
|
+
setAuthUrl: (url: string) => void;
|
|
25
|
+
}
|
|
18
26
|
/**
|
|
19
|
-
* Start a local HTTP server
|
|
27
|
+
* Start a local HTTP server for OAuth callback.
|
|
20
28
|
*
|
|
21
|
-
*
|
|
29
|
+
* Returns a promise that resolves once the server is listening (port acquired),
|
|
30
|
+
* or rejects immediately if the port is taken (EADDRINUSE). This two-phase
|
|
31
|
+
* design lets callers confirm they own the port before opening a browser tab,
|
|
32
|
+
* eliminating the race where two processes both check the port, both find it
|
|
33
|
+
* free, and both open duplicate tabs.
|
|
22
34
|
*/
|
|
23
|
-
export declare function startCallbackServer(options?: CallbackServerOptions): Promise<
|
|
35
|
+
export declare function startCallbackServer(options?: CallbackServerOptions): Promise<CallbackServerHandle>;
|
|
24
36
|
/**
|
|
25
37
|
* Get the callback URL for OAuth configuration
|
|
26
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/auth/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/auth/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,eAAe,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,yDAAyD;IACzD,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,oEAAoE;IACpE,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA2KtG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAe,GAAG,MAAM,CAE1D"}
|
package/dist/auth/server.js
CHANGED
|
@@ -8,9 +8,13 @@ import { createServer } from "node:http";
|
|
|
8
8
|
const DEFAULT_PORT = 19842;
|
|
9
9
|
const TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
10
10
|
/**
|
|
11
|
-
* Start a local HTTP server
|
|
11
|
+
* Start a local HTTP server for OAuth callback.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* Returns a promise that resolves once the server is listening (port acquired),
|
|
14
|
+
* or rejects immediately if the port is taken (EADDRINUSE). This two-phase
|
|
15
|
+
* design lets callers confirm they own the port before opening a browser tab,
|
|
16
|
+
* eliminating the race where two processes both check the port, both find it
|
|
17
|
+
* free, and both open duplicate tabs.
|
|
14
18
|
*/
|
|
15
19
|
export function startCallbackServer(options = {}) {
|
|
16
20
|
const port = options.port || DEFAULT_PORT;
|
|
@@ -26,11 +30,14 @@ export function startCallbackServer(options = {}) {
|
|
|
26
30
|
// Grace period: keep server alive after timeout so the user sees a styled
|
|
27
31
|
// error page instead of "This site can't be reached" if they click Allow late.
|
|
28
32
|
const GRACE_PERIOD_MS = 5 * 60 * 1000; // 5 minutes
|
|
29
|
-
return new Promise((
|
|
33
|
+
return new Promise((resolveStart, rejectStart) => {
|
|
30
34
|
let server = null;
|
|
31
35
|
let timeoutId = null;
|
|
32
36
|
let graceTimeoutId = null;
|
|
33
37
|
let timedOut = false;
|
|
38
|
+
let callbackResolve = null;
|
|
39
|
+
let callbackReject = null;
|
|
40
|
+
let authUrl = null;
|
|
34
41
|
const cleanup = () => {
|
|
35
42
|
if (timeoutId) {
|
|
36
43
|
clearTimeout(timeoutId);
|
|
@@ -45,30 +52,57 @@ export function startCallbackServer(options = {}) {
|
|
|
45
52
|
server = null;
|
|
46
53
|
}
|
|
47
54
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const resetTimeout = () => {
|
|
56
|
+
if (timeoutId) {
|
|
57
|
+
clearTimeout(timeoutId);
|
|
58
|
+
}
|
|
59
|
+
if (graceTimeoutId) {
|
|
60
|
+
clearTimeout(graceTimeoutId);
|
|
61
|
+
graceTimeoutId = null;
|
|
62
|
+
}
|
|
63
|
+
timedOut = false;
|
|
64
|
+
timeoutId = setTimeout(() => {
|
|
65
|
+
timedOut = true;
|
|
66
|
+
timeoutId = null;
|
|
67
|
+
// If no auth URL for retry, reject immediately
|
|
68
|
+
if (!authUrl) {
|
|
69
|
+
callbackReject?.(new Error("OAuth callback timeout - no response received within 5 minutes"));
|
|
70
|
+
}
|
|
71
|
+
// Keep server alive so user can see retry page or error page
|
|
72
|
+
graceTimeoutId = setTimeout(() => {
|
|
73
|
+
callbackReject?.(new Error("OAuth callback timeout - no response after retry period"));
|
|
74
|
+
cleanup();
|
|
75
|
+
}, GRACE_PERIOD_MS);
|
|
76
|
+
}, timeout);
|
|
77
|
+
};
|
|
58
78
|
server = createServer((req, res) => {
|
|
59
79
|
log("Received request:", req.url);
|
|
80
|
+
// Handle retry: redirect back to auth URL and reset timeout
|
|
81
|
+
if (req.url?.startsWith("/retry") && authUrl) {
|
|
82
|
+
log("Retry requested, redirecting to auth URL");
|
|
83
|
+
resetTimeout();
|
|
84
|
+
res.writeHead(302, { Location: authUrl });
|
|
85
|
+
res.end();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
60
88
|
// Only handle GET /callback
|
|
61
89
|
if (!req.url?.startsWith("/callback")) {
|
|
62
90
|
res.writeHead(404);
|
|
63
91
|
res.end("Not Found");
|
|
64
92
|
return;
|
|
65
93
|
}
|
|
66
|
-
// If auth timed out, show
|
|
94
|
+
// If auth timed out, show retry page (if auth URL available) or error page
|
|
67
95
|
if (timedOut) {
|
|
68
|
-
log("Received callback after timeout, serving error page");
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
96
|
+
log("Received callback after timeout, serving retry/error page");
|
|
97
|
+
if (authUrl) {
|
|
98
|
+
res.writeHead(408, { "Content-Type": "text/html" });
|
|
99
|
+
res.end(renderRetryPage("Authentication timed out.", `http://localhost:${port}/retry`, serverName));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
res.writeHead(408, { "Content-Type": "text/html" });
|
|
103
|
+
res.end(renderErrorPage("Authentication timed out. Please close this tab and restart the connection from your application."));
|
|
104
|
+
cleanup();
|
|
105
|
+
}
|
|
72
106
|
return;
|
|
73
107
|
}
|
|
74
108
|
const url = new URL(req.url, `http://localhost:${port}`);
|
|
@@ -82,7 +116,7 @@ export function startCallbackServer(options = {}) {
|
|
|
82
116
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
83
117
|
res.end(renderErrorPage("Authorization failed. Please close this window and try again."));
|
|
84
118
|
cleanup();
|
|
85
|
-
|
|
119
|
+
callbackReject?.(new Error(`OAuth error: ${error}${errorDescription ? ` - ${errorDescription}` : ""}`));
|
|
86
120
|
return;
|
|
87
121
|
}
|
|
88
122
|
// Handle missing code
|
|
@@ -91,7 +125,7 @@ export function startCallbackServer(options = {}) {
|
|
|
91
125
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
92
126
|
res.end(renderErrorPage("No authorization code received. Please try again."));
|
|
93
127
|
cleanup();
|
|
94
|
-
|
|
128
|
+
callbackReject?.(new Error("No authorization code received"));
|
|
95
129
|
return;
|
|
96
130
|
}
|
|
97
131
|
// Success!
|
|
@@ -99,19 +133,30 @@ export function startCallbackServer(options = {}) {
|
|
|
99
133
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
100
134
|
res.end(renderSuccessPage(serverName));
|
|
101
135
|
cleanup();
|
|
102
|
-
|
|
136
|
+
callbackResolve?.({ code, state: state || undefined });
|
|
103
137
|
});
|
|
104
138
|
server.on("error", (err) => {
|
|
105
139
|
cleanup();
|
|
106
140
|
if (err.code === "EADDRINUSE") {
|
|
107
|
-
|
|
141
|
+
rejectStart(new Error(`Port ${port} is already in use. Is another gateway login in progress?`));
|
|
108
142
|
}
|
|
109
143
|
else {
|
|
110
|
-
|
|
144
|
+
rejectStart(err);
|
|
111
145
|
}
|
|
112
146
|
});
|
|
113
147
|
server.listen(port, "127.0.0.1", () => {
|
|
114
148
|
log(`Callback server listening on http://localhost:${port}/callback`);
|
|
149
|
+
// Server is now listening; set up the callback timeout
|
|
150
|
+
resetTimeout();
|
|
151
|
+
// Return the handle so the caller can open the browser and then wait
|
|
152
|
+
resolveStart({
|
|
153
|
+
waitForCallback: () => new Promise((resolve, reject) => {
|
|
154
|
+
callbackResolve = resolve;
|
|
155
|
+
callbackReject = reject;
|
|
156
|
+
}),
|
|
157
|
+
close: cleanup,
|
|
158
|
+
setAuthUrl: (url) => { authUrl = url; },
|
|
159
|
+
});
|
|
115
160
|
});
|
|
116
161
|
});
|
|
117
162
|
}
|
|
@@ -348,6 +393,24 @@ function pageShell(content) {
|
|
|
348
393
|
background: rgba(59, 130, 246, 0.2);
|
|
349
394
|
border-color: rgba(59, 130, 246, 0.3);
|
|
350
395
|
}
|
|
396
|
+
.btn-secondary {
|
|
397
|
+
background: rgba(255, 255, 255, 0.06);
|
|
398
|
+
color: var(--muted);
|
|
399
|
+
border: 1px solid var(--card-border);
|
|
400
|
+
}
|
|
401
|
+
.btn-secondary:hover {
|
|
402
|
+
background: rgba(255, 255, 255, 0.1);
|
|
403
|
+
}
|
|
404
|
+
@media (prefers-color-scheme: light) {
|
|
405
|
+
.btn-secondary {
|
|
406
|
+
background: rgba(0, 0, 0, 0.04);
|
|
407
|
+
color: #666;
|
|
408
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
409
|
+
}
|
|
410
|
+
.btn-secondary:hover {
|
|
411
|
+
background: rgba(0, 0, 0, 0.08);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
351
414
|
.wordmark {
|
|
352
415
|
position: relative;
|
|
353
416
|
z-index: 10;
|
|
@@ -430,6 +493,30 @@ function renderSuccessPage(serverName) {
|
|
|
430
493
|
</div>
|
|
431
494
|
</div>`);
|
|
432
495
|
}
|
|
496
|
+
function renderRetryPage(message, retryUrl, serverName) {
|
|
497
|
+
const displayName = serverName ? capitalize(escapeHtml(serverName)) : "the service";
|
|
498
|
+
return pageShell(`
|
|
499
|
+
<div class="card">
|
|
500
|
+
<div class="card-header">
|
|
501
|
+
<div class="logo-container">
|
|
502
|
+
<div class="logo-box">${SONOMA_LOGO}</div>
|
|
503
|
+
</div>
|
|
504
|
+
<div class="error-icon">
|
|
505
|
+
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
506
|
+
<circle cx="12" cy="12" r="10"/>
|
|
507
|
+
<line x1="12" y1="8" x2="12" y2="12"/>
|
|
508
|
+
<line x1="12" y1="16" x2="12.01" y2="16"/>
|
|
509
|
+
</svg>
|
|
510
|
+
</div>
|
|
511
|
+
<div class="title">Authentication Timed Out</div>
|
|
512
|
+
<p class="description">${escapeHtml(message)} Click retry to authenticate with <strong>${displayName}</strong> again.</p>
|
|
513
|
+
</div>
|
|
514
|
+
<div class="card-footer" style="display:flex;gap:12px;justify-content:center">
|
|
515
|
+
<a class="btn btn-cta" href="${escapeHtml(retryUrl)}" style="cursor:pointer!important">Retry</a>
|
|
516
|
+
<button class="btn btn-secondary" onclick="window.close()" style="cursor:pointer!important">Close</button>
|
|
517
|
+
</div>
|
|
518
|
+
</div>`);
|
|
519
|
+
}
|
|
433
520
|
function renderErrorPage(message) {
|
|
434
521
|
return pageShell(`
|
|
435
522
|
<div class="card">
|
package/dist/auth/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/auth/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AAEjG,MAAM,YAAY,GAAG,KAAK,CAAC;AAC3B,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/auth/server.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/storage.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Secure token storage for MCP Gateway OAuth credentials
|
|
3
3
|
*
|
|
4
|
-
* Stores tokens in
|
|
5
|
-
*
|
|
6
|
-
* tokens from being copied between machines.
|
|
4
|
+
* Stores tokens in the OS keychain (macOS Keychain, Windows Credential Manager).
|
|
5
|
+
* Falls back to encrypted file storage on unsupported platforms.
|
|
7
6
|
*/
|
|
8
7
|
import type { OAuthTokens, OAuthClientInformationMixed } from "@modelcontextprotocol/sdk/shared/auth.js";
|
|
9
8
|
export interface StoredCredentials {
|
|
@@ -20,15 +19,15 @@ export interface StoredCredentials {
|
|
|
20
19
|
lastRefreshed?: number;
|
|
21
20
|
}
|
|
22
21
|
/**
|
|
23
|
-
* Load stored credentials from
|
|
22
|
+
* Load stored credentials from OS keychain (or legacy file).
|
|
24
23
|
*/
|
|
25
24
|
export declare function loadCredentials(): StoredCredentials | null;
|
|
26
25
|
/**
|
|
27
|
-
* Save credentials to
|
|
26
|
+
* Save credentials to OS keychain (or fallback file).
|
|
28
27
|
*/
|
|
29
28
|
export declare function saveCredentials(credentials: StoredCredentials): void;
|
|
30
29
|
/**
|
|
31
|
-
* Clear all stored credentials
|
|
30
|
+
* Clear all stored credentials.
|
|
32
31
|
*/
|
|
33
32
|
export declare function clearCredentials(): void;
|
|
34
33
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AAQzG,MAAM,WAAW,iBAAiB;IAEhC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAG/B,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,iBAAiB,GAAG,IAAI,CA4B1D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAgBpE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAQvC;AAkBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,WAAW,GAAG,SAAS,CAY/E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAYpG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,2BAA2B,GAAG,SAAS,CAUrG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,SAAQ,GAAG,OAAO,CAMlF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAEjE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
|