Skip to content

fix(auth): prevent OAuth stdout corruption and handle expired tokens#115

Open
timothedelion wants to merge 1 commit intomainfrom
fix/oauth-stdio-corruption-and-expired-token-handling
Open

fix(auth): prevent OAuth stdout corruption and handle expired tokens#115
timothedelion wants to merge 1 commit intomainfrom
fix/oauth-stdio-corruption-and-expired-token-handling

Conversation

@timothedelion
Copy link
Copy Markdown
Collaborator

Summary

  • Replace print() with logger.info() in OAuth flowprint() writes to stdout, which is the MCP JSON-RPC channel in stdio mode. This corrupted the protocol and caused Claude Code CLI to report ✗ Failed to connect on health check, with all tool calls silently rejected.
  • Return expired tokens from FileTokenStorage instead of None — Previously, an expired stored token caused acquire_single_tenant_token() to fall through to the interactive OAuth flow, blocking server startup for up to 5 minutes. Now the expired token is returned and the API validates it; the existing 401 → _refresh_token() path handles re-authentication automatically.
  • Add 30s timeout on scope fetching during lifespan — If a 401 retry triggers an OAuth re-auth flow during startup, the server won't block indefinitely. After 30s it starts with empty scopes; common tools (get_authenticated_user_info, revoke_current_token) remain available since they have no required_scopes.

Test plan

  • All 439 existing tests pass
  • With an expired token in ~/Library/Application Support/GitGuardian/mcp_oauth_tokens.json, verify the server starts and connects to Claude Code (no Failed to connect)
  • Verify OAuth banners no longer appear in MCP protocol output (stdout is clean JSON-RPC only)
  • Verify that an expired token triggers automatic re-authentication via the 401 handler rather than a blocking interactive OAuth flow
  • With a valid token, verify normal operation is unaffected

…nd handle expired tokens gracefully

OAuth print() calls wrote banners to stdout, which is the MCP JSON-RPC
channel in stdio mode. This corrupted the protocol and caused Claude Code
to report "Failed to connect". Additionally, expired stored tokens
triggered a blocking 5-minute interactive OAuth flow during server
startup instead of letting the API validate and the 401 handler
re-authenticate automatically.

Changes:
- Replace all print() with logger.info() in oauth.py to keep stdout clean
- Return expired tokens from FileTokenStorage instead of None, deferring
  validation to the API and leveraging the existing 401 refresh handler
- Add 30s timeout on scope fetching during lifespan to prevent indefinite
  blocking if re-authentication is triggered at startup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant