@lifeaitools/clauth 1.5.9 → 1.5.11
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/cli/commands/serve.js +14 -17
- package/package.json +1 -1
package/cli/commands/serve.js
CHANGED
|
@@ -2505,7 +2505,16 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
|
|
|
2505
2505
|
// ── OAuth provider (self-contained for claude.ai MCP) ──────
|
|
2506
2506
|
const oauthClients = new Map(); // client_id → { client_secret, redirect_uris, client_name }
|
|
2507
2507
|
const oauthCodes = new Map(); // code → { client_id, redirect_uri, code_challenge, expires }
|
|
2508
|
-
|
|
2508
|
+
|
|
2509
|
+
// Persist tokens to disk so daemon restarts don't invalidate claude.ai sessions
|
|
2510
|
+
const TOKENS_FILE = path.join(os.tmpdir(), "clauth-oauth-tokens.json");
|
|
2511
|
+
function loadTokens() {
|
|
2512
|
+
try { return new Set(JSON.parse(fs.readFileSync(TOKENS_FILE, "utf8"))); } catch { return new Set(); }
|
|
2513
|
+
}
|
|
2514
|
+
function saveTokens(set) {
|
|
2515
|
+
try { fs.writeFileSync(TOKENS_FILE, JSON.stringify([...set])); } catch {}
|
|
2516
|
+
}
|
|
2517
|
+
const oauthTokens = loadTokens(); // active access tokens — persisted across restarts
|
|
2509
2518
|
|
|
2510
2519
|
// Pre-generate a stable client for claude.ai (shown at startup)
|
|
2511
2520
|
const OAUTH_CLIENT_ID = crypto.randomBytes(16).toString("hex");
|
|
@@ -2998,6 +3007,7 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
|
|
|
2998
3007
|
oauthCodes.delete(body.code);
|
|
2999
3008
|
const accessToken = crypto.randomBytes(32).toString("hex");
|
|
3000
3009
|
oauthTokens.add(accessToken);
|
|
3010
|
+
saveTokens(oauthTokens);
|
|
3001
3011
|
|
|
3002
3012
|
const logMsg = `[${new Date().toISOString()}] OAuth: token issued for client ${stored.client_id}\n`;
|
|
3003
3013
|
try { fs.appendFileSync(LOG_FILE, logMsg); } catch {}
|
|
@@ -3025,9 +3035,11 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
|
|
|
3025
3035
|
const authHeader = req.headers.authorization;
|
|
3026
3036
|
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
3027
3037
|
const base = oauthBase();
|
|
3038
|
+
// Path-specific resource metadata URL so claude.ai gets the right resource URI
|
|
3039
|
+
const pathName = reqPath === "/mcp" ? "mcp" : reqPath.slice(1);
|
|
3028
3040
|
res.writeHead(401, {
|
|
3029
3041
|
"Content-Type": "application/json",
|
|
3030
|
-
"WWW-Authenticate": `Bearer resource_metadata="${base}/.well-known/oauth-protected-resource"`,
|
|
3042
|
+
"WWW-Authenticate": `Bearer resource_metadata="${base}/.well-known/oauth-protected-resource/${pathName}"`,
|
|
3031
3043
|
...CORS,
|
|
3032
3044
|
});
|
|
3033
3045
|
return res.end(JSON.stringify({ error: "unauthorized" }));
|
|
@@ -3042,21 +3054,6 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
|
|
|
3042
3054
|
// fall through to MCP handling below
|
|
3043
3055
|
}
|
|
3044
3056
|
|
|
3045
|
-
// For namespaced paths, send path-specific 401 so claude.ai fetches the right resource metadata
|
|
3046
|
-
if (method === "POST" && (reqPath === "/gws" || reqPath === "/clauth")) {
|
|
3047
|
-
const authHeader = req.headers.authorization;
|
|
3048
|
-
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
3049
|
-
const base = oauthBase();
|
|
3050
|
-
const pathName = reqPath.slice(1); // "gws" or "clauth"
|
|
3051
|
-
res.writeHead(401, {
|
|
3052
|
-
"Content-Type": "application/json",
|
|
3053
|
-
"WWW-Authenticate": `Bearer resource_metadata="${base}/.well-known/oauth-protected-resource/${pathName}"`,
|
|
3054
|
-
...CORS,
|
|
3055
|
-
});
|
|
3056
|
-
return res.end(JSON.stringify({ error: "unauthorized" }));
|
|
3057
|
-
}
|
|
3058
|
-
}
|
|
3059
|
-
|
|
3060
3057
|
// ── MCP Streamable HTTP transport (2025-03-26 spec) ──
|
|
3061
3058
|
// POST /sse, /mcp, /gws, /clauth — JSON-RPC over HTTP
|
|
3062
3059
|
if (method === "POST" && (reqPath === "/sse" || isMcpPath)) {
|