@lifeaitools/clauth 1.5.24 → 1.5.25

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.
@@ -2962,7 +2962,7 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
2962
2962
  token_endpoint: `${base}/token`,
2963
2963
  registration_endpoint: `${base}/register`,
2964
2964
  response_types_supported: ["code"],
2965
- grant_types_supported: ["authorization_code"],
2965
+ grant_types_supported: ["authorization_code", "client_credentials"],
2966
2966
  code_challenge_methods_supported: ["S256"],
2967
2967
  scopes_supported: ["mcp:tools"],
2968
2968
  }));
@@ -3038,6 +3038,23 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3038
3038
  return res.end(JSON.stringify({ error: "invalid_request" }));
3039
3039
  }
3040
3040
 
3041
+ // client_credentials grant — skip authorize/redirect, just issue token from client_id+secret
3042
+ if (body.grant_type === "client_credentials") {
3043
+ const cid = body.client_id;
3044
+ const csec = body.client_secret;
3045
+ if (cid === OAUTH_CLIENT_ID && csec === OAUTH_CLIENT_SECRET) {
3046
+ const accessToken = crypto.randomBytes(32).toString("hex");
3047
+ oauthTokens.add(accessToken);
3048
+ saveTokens(oauthTokens);
3049
+ const logMsg = `[${new Date().toISOString()}] OAuth: client_credentials token issued for ${cid.slice(0,8)}… (token=${accessToken.slice(0,8)}…)\n`;
3050
+ try { fs.appendFileSync(LOG_FILE, logMsg); } catch {}
3051
+ res.writeHead(200, { "Content-Type": "application/json", ...CORS });
3052
+ return res.end(JSON.stringify({ access_token: accessToken, token_type: "Bearer", expires_in: 86400, scope: "mcp:tools" }));
3053
+ }
3054
+ res.writeHead(401, { "Content-Type": "application/json", ...CORS });
3055
+ return res.end(JSON.stringify({ error: "invalid_client" }));
3056
+ }
3057
+
3041
3058
  if (body.grant_type !== "authorization_code") {
3042
3059
  res.writeHead(400, { "Content-Type": "application/json", ...CORS });
3043
3060
  return res.end(JSON.stringify({ error: "unsupported_grant_type" }));
@@ -3114,15 +3131,20 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3114
3131
  return res.end(JSON.stringify({ error: "unauthorized" }));
3115
3132
  }
3116
3133
  const token = authHeader.slice(7);
3117
- if (!oauthTokens.has(token)) {
3118
- const logMsg = `[${new Date().toISOString()}] OAuth: REJECTED token ${token.slice(0,8)}… (pool=${oauthTokens.size})\n`;
3134
+ // Accept: OAuth-issued tokens OR the stable client_secret directly
3135
+ const isValidToken = oauthTokens.has(token) || token === OAUTH_CLIENT_SECRET;
3136
+ if (!isValidToken) {
3137
+ const logMsg = `[${new Date().toISOString()}] OAuth: REJECTED token ${token.slice(0,8)}… (pool=${oauthTokens.size}, secret=${token === OAUTH_CLIENT_SECRET})\n`;
3119
3138
  try { fs.appendFileSync(LOG_FILE, logMsg); } catch {}
3120
3139
  res.writeHead(401, { "Content-Type": "application/json", ...CORS });
3121
3140
  return res.end(JSON.stringify({ error: "invalid_token" }));
3122
3141
  }
3123
3142
  req._clauthRemote = true;
3124
- } else if (authHeader?.startsWith("Bearer ") && oauthTokens.has(authHeader.slice(7))) {
3125
- req._clauthRemote = true;
3143
+ } else if (authHeader?.startsWith("Bearer ")) {
3144
+ const token = authHeader.slice(7);
3145
+ if (oauthTokens.has(token) || token === OAUTH_CLIENT_SECRET) {
3146
+ req._clauthRemote = true;
3147
+ }
3126
3148
  }
3127
3149
  // fall through to MCP handling
3128
3150
  }
@@ -3200,7 +3222,8 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3200
3222
  });
3201
3223
  return res.end(JSON.stringify({ error: "unauthorized" }));
3202
3224
  }
3203
- if (!oauthTokens.has(authHeader.slice(7))) {
3225
+ const sseToken = authHeader.slice(7);
3226
+ if (!oauthTokens.has(sseToken) && sseToken !== OAUTH_CLIENT_SECRET) {
3204
3227
  res.writeHead(401, { "Content-Type": "application/json", ...CORS });
3205
3228
  return res.end(JSON.stringify({ error: "invalid_token" }));
3206
3229
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/clauth",
3
- "version": "1.5.24",
3
+ "version": "1.5.25",
4
4
  "description": "Hardware-bound credential vault for the LIFEAI infrastructure stack",
5
5
  "type": "module",
6
6
  "bin": {