somratpro Claude Sonnet 4.6 commited on
Commit
f9ac23b
Β·
1 Parent(s): 062df28

debug: add Redis codeVerifier check to /app/debug-logs

Browse files

Add REDIS codeVerifier CHECK section to debug-logs endpoint:
- Lists all login:* keys in Redis
- For each key: shows oauth_token length, oauth_token_secret length,
TTL remaining, and detects structural issues:
* No colon β†’ split fails β†’ empty secret β†’ wrong OAuth signature β†’ 500
* Extra colons β†’ secret truncated β†’ wrong signature
* Secret too short β†’ might be truncated/corrupted
- Cross-checks with callback log to verify token/secret are present

This tests the theory that oauth_token_secret corruption in Redis
is causing X's oauth/access_token to return 500.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. health-server.js +46 -0
health-server.js CHANGED
@@ -1938,6 +1938,50 @@ const server = http.createServer((req, res) => {
1938
  ? fs.readFileSync("/tmp/x-oauth-callbacks.log", "utf8")
1939
  : "(no X callbacks recorded yet β€” try adding X channel now)";
1940
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1941
  const out = [
1942
  credSection,
1943
  "",
@@ -1946,6 +1990,8 @@ const server = http.createServer((req, res) => {
1946
  "=== X OAUTH CALLBACKS (from health-server) ===",
1947
  xCallbackLog,
1948
  "",
 
 
1949
  "=== BACKEND ERROR LOG (last 150 lines) ===",
1950
  errLog,
1951
  "",
 
1938
  ? fs.readFileSync("/tmp/x-oauth-callbacks.log", "utf8")
1939
  : "(no X callbacks recorded yet β€” try adding X channel now)";
1940
 
1941
+ // Redis check: look up login:* keys and verify codeVerifier structure.
1942
+ // Root cause check: oauth_token_secret must be present after split on ':'.
1943
+ let redisSection = "=== REDIS codeVerifier CHECK ===\n";
1944
+ try {
1945
+ const { execSync } = require("child_process");
1946
+ const keys = execSync(
1947
+ 'redis-cli -h 127.0.0.1 -p 6379 keys "login:*" 2>/dev/null', { timeout: 5000 }
1948
+ ).toString().trim();
1949
+
1950
+ if (!keys) {
1951
+ redisSection += "(no login:* keys in Redis β€” request_token may not have been called yet)";
1952
+ } else {
1953
+ redisSection += `Found keys:\n`;
1954
+ for (const key of keys.split("\n").filter(Boolean).slice(0, 5)) {
1955
+ const val = execSync(
1956
+ `redis-cli -h 127.0.0.1 -p 6379 get "${key}" 2>/dev/null`, { timeout: 5000 }
1957
+ ).toString().trim();
1958
+ const ttl = execSync(
1959
+ `redis-cli -h 127.0.0.1 -p 6379 ttl "${key}" 2>/dev/null`, { timeout: 5000 }
1960
+ ).toString().trim();
1961
+ if (!val) {
1962
+ redisSection += ` ${key}: (empty or missing!)\n`;
1963
+ continue;
1964
+ }
1965
+ const colonIdx = val.indexOf(":");
1966
+ const token = colonIdx > 0 ? val.slice(0, colonIdx) : "(none β€” no colon found!)";
1967
+ const secret = colonIdx > 0 ? val.slice(colonIdx + 1) : "(none β€” no colon found!)";
1968
+ const extraColons = (val.match(/:/g) || []).length - 1;
1969
+ const tokenShow = token.slice(0, 12) + "... (len=" + token.length + ")";
1970
+ const secretShow = secret.slice(0, 12) + "... (len=" + secret.length + ")";
1971
+ const note = colonIdx < 0
1972
+ ? "⚠ NO COLON β€” split will fail β†’ empty secret β†’ bad signature!"
1973
+ : extraColons > 0
1974
+ ? `⚠ ${extraColons} extra colon(s) in value β€” split(':')[1] truncates secret!`
1975
+ : secret.length < 30
1976
+ ? "⚠ secret looks short β€” might be truncated"
1977
+ : "βœ“ format ok";
1978
+ redisSection += ` ${key}\n token : ${tokenShow}\n secret: ${secretShow}\n ttl : ${ttl}s\n note : ${note}\n`;
1979
+ }
1980
+ }
1981
+ } catch (e) {
1982
+ redisSection += `(redis-cli error: ${e.message})`;
1983
+ }
1984
+
1985
  const out = [
1986
  credSection,
1987
  "",
 
1990
  "=== X OAUTH CALLBACKS (from health-server) ===",
1991
  xCallbackLog,
1992
  "",
1993
+ redisSection,
1994
+ "",
1995
  "=== BACKEND ERROR LOG (last 150 lines) ===",
1996
  errLog,
1997
  "",