Skip to content

Fix several bugs in the OAuth implementation#7

Merged
indragiek merged 7 commits intomainfrom
oauth-bug-fixes
Jul 3, 2025
Merged

Fix several bugs in the OAuth implementation#7
indragiek merged 7 commits intomainfrom
oauth-bug-fixes

Conversation

@indragiek
Copy link
Owner

No description provided.

indragiek and others added 5 commits July 3, 2025 09:59
This is already validated in `OAuthClient.buildAuthenticationURL`
This is a developer tool, so we can afford to be less secure by default to simplify the process of testing local servers during development
Explanation from Claude:

1. Root Cause: When showing the authentication sheet for token refresh, ServerFeature
  was only retrieving the token but not the associated clientID from the keychain. This
  caused it to use the default clientID ("com.indragie.Context") instead of the
  dynamically registered one.
  2. The Fix:
    - Modified ServerFeature to retrieve the full StoredOAuthToken (which includes both
  token and clientID)
    - Updated the showAuthenticationSheet action to include the clientID parameter
    - Modified AuthenticationFeature.State initializer to accept and use the stored
  clientID

  This ensures that during token refresh, the app uses the same clientID that was
  registered during the initial authentication, preventing the "invalid_client: Client
  not found" error.

  The app now properly handles OAuth servers that use dynamic client registration and
  should successfully refresh tokens when they expire.
When the background token refresh timer fails to refresh an OAuth token,
the user was not notified and the authentication UI was not presented.
This commit adds a callback mechanism that allows MCPClientManager to
notify ServerFeature when token refresh fails, triggering the authentication
modal to allow the user to re-authenticate.

Changes:
- Add tokenRefreshFailureCallbacks to MCPClientManager for notification
- Register/unregister callbacks in ServerFeature lifecycle
- Show authentication UI when automatic refresh fails
- Properly handle Swift 6 @sendable requirements

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
When creating a new client connection, if an expired token with a refresh
token is detected, the system now attempts to refresh the token automatically
before throwing an authentication error. This provides a better user experience
by avoiding unnecessary re-authentication when a valid refresh token exists.

Changes:
- Modified createClient to attempt token refresh on authentication errors
- Updated createTransport to not delete expired tokens immediately
- Token refresh is now attempted before propagating authentication errors

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@claude
Copy link

claude bot commented Jul 3, 2025

Claude finished @indragiek's task —— View job


Pull Request Review: OAuth Bug Fixes

I've completed a comprehensive review of the OAuth bug fixes. Here's my detailed analysis:

Review Checklist:

  • Read and analyze AuthenticationFeature.swift changes
  • Read and analyze MCPClientManager.swift changes
  • Read and analyze ServerFeature.swift changes
  • Read and analyze OAuthClient.swift changes
  • Check OAuth security best practices
  • Review error handling and edge cases
  • Assess code quality and Swift best practices
  • Provide comprehensive feedback

🔒 Security Analysis

Strengths

  • PKCE Implementation: Proper S256 method with secure random generation (AuthenticationFeature.swift:298)
  • State Parameter Validation: Constant-time comparison prevents timing attacks (AuthenticationFeature.swift:615-622)
  • Token Expiration Handling: Proper checks before using stored tokens (MCPClientManager.swift:225)
  • Sensitive Data Clearing: clearSensitiveData() properly removes OAuth state and PKCE parameters (AuthenticationFeature.swift:175-179)

⚠️ Security Concerns

  • Authorization Code Validation: Basic length check only (AuthenticationFeature.swift:377). Consider validating format/charset
  • Token Refresh Logging: Silent refresh still logs token operations - potential info leak (AuthenticationFeature.swift:216)
  • Metadata Caching: Token refresh rediscovers metadata every time - could cache with TTL for performance

🐛 Potential Bugs & Issues

Race Conditions

  • Token Refresh: Well-handled with isRefreshing flag and active task tracking (MCPClientManager.swift:369-373)
  • Authentication State: Proper checks prevent duplicate auth sheets (ServerFeature.swift:454)

Error Handling

  • Generic Error Messages: Crypto failures show generic "Failed to generate secure state parameter" (AuthenticationFeature.swift:241)
  • Keychain Failures: Connection error handler accesses keychain without proper error handling (ServerFeature.swift:240)

Edge Cases

  • Token Refresh Timer: Starts on first access, could delay refresh checks (MCPClientManager.swift:304-307)
  • Reconnection Logic: Only attempts once - missing exponential backoff (ServerFeature.swift:388)
  • Expired Token Check: Should verify token isn't already expired before refresh window (MCPClientManager.swift:336)

📊 Code Quality Assessment

Excellent Practices

  • Async/Await Usage: Modern Swift concurrency patterns throughout
  • Error Propagation: Proper error typing and propagation
  • State Management: Clean TCA reducer pattern with proper state isolation
  • Resource Management: Proper cleanup in deinit and cancellation handling

🔄 Improvement Opportunities

  • Duplicate Code: Keychain access patterns repeated across files
  • Magic Numbers: Hardcoded timeouts (60s, 300s) could be configurable (MCPClientManager.swift:25-26)
  • Logging Consistency: Some areas over-log, others under-log sensitive operations

🚀 Performance Considerations

Efficient Implementation

  • Concurrent Refresh Prevention: Reuses existing refresh tasks (MCPClientManager.swift:370-372)
  • Connection State Caching: Avoids unnecessary state checks
  • Timer-Based Refresh: Proactive token refresh prevents authentication failures

💡 Performance Suggestions

  • Metadata Caching: Cache authorization server metadata with TTL
  • Batch Operations: Token refresh could batch multiple server refreshes
  • Connection Pooling: Consider connection reuse for multiple auth operations

🧪 Test Coverage Recommendations

Critical Test Cases

  1. Token Refresh Failures: Test network failures, invalid refresh tokens, expired tokens
  2. Race Conditions: Concurrent token refresh attempts, multiple authentication flows
  3. Security Validation: State parameter tampering, CSRF attacks, code injection
  4. Error Recovery: Authentication failure recovery, keychain access failures
  5. Edge Cases: Token expiration during refresh, metadata discovery failures

Integration Tests

  • End-to-end OAuth flow with real authorization server
  • Token refresh during active connections
  • Authentication failure and recovery scenarios

📝 Recommendations

High Priority

  1. Add metadata caching to reduce network calls during token refresh
  2. Implement exponential backoff for reconnection attempts
  3. Enhance authorization code validation beyond basic length checks
  4. Add proper error handling for keychain operations

Medium Priority

  1. Make timing constants configurable (refresh intervals, timeouts)
  2. Reduce logging of sensitive operations in production
  3. Add more specific error messages for crypto failures
  4. Consider connection pooling for auth operations

Low Priority

  1. Refactor duplicate keychain access patterns
  2. Add more comprehensive logging for debugging
  3. Consider retry mechanisms for transient failures

🎯 Overall Assessment

This is a solid implementation of OAuth bug fixes with good security practices and proper error handling. The code demonstrates:

  • ✅ Strong security posture with PKCE and state validation
  • ✅ Proper async/await patterns and resource management
  • ✅ Good separation of concerns and clean architecture
  • ✅ Comprehensive error handling and user feedback

The changes address the core OAuth issues while maintaining code quality and security standards. The automatic token refresh mechanism is particularly well-implemented.

Recommendation: Approve with minor improvements suggested above.


indragiek and others added 2 commits July 3, 2025 10:45
Addresses PR review feedback by reducing sensitive information in logs:
- Changed token-specific log messages to use generic "authentication" terminology
- Reduced log levels from info to debug for routine authentication operations
- Avoided logging during silent token refresh to prevent information leaks
- Kept authorization code validation as-is since OAuth 2.0 spec doesn't define format

This improves security by preventing sensitive token information from appearing
in logs while maintaining useful debugging capabilities.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Addresses PR review feedback:

1. Generic Error Messages: Replaced generic crypto failure messages with more
   specific error descriptions that help users understand the issue
   - Added proper error type checking for OAuthClientError
   - Provided specific message for randomGenerationFailed indicating potential system security issue
   - Added fallback for unexpected errors with their descriptions

2. Keychain Failures: Added proper error handling for keychain access
   - Wrapped keychain access in do-catch blocks instead of using try?
   - Log errors but continue with authentication flow
   - User can still authenticate even if old token retrieval fails

This improves user experience by providing clearer error messages and prevents
authentication flow from being blocked by non-critical keychain failures.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@claude
Copy link

claude bot commented Jul 3, 2025

Claude finished @indragiek's task —— View job


I'll provide a comprehensive review of the OAuth bug fixes. Let me analyze the changes systematically.

Review Progress

  • Check for repository guidelines (CLAUDE.md)
  • Analyze AuthenticationFeature.swift changes
  • Analyze MCPClientManager.swift changes
  • Analyze ServerFeature.swift changes
  • Analyze OAuthClient.swift changes
  • Review OAuth security best practices
  • Check for potential bugs and edge cases
  • Assess performance considerations
  • Evaluate Swift code quality and best practices
  • Provide comprehensive feedback with recommendations

🔒 Security Analysis

Excellent Security Practices

  • PKCE Implementation: Proper S256 method with 64-byte secure random verifier (OAuthClient.swift:360-378)
  • State Parameter Protection: Cryptographically secure generation and constant-time comparison prevents timing attacks (OAuthClient.swift:615-622, AuthenticationFeature.swift:380-387)
  • Token Expiration Handling: Proactive checks before using stored tokens (MCPClientManager.swift:225)
  • Sensitive Data Management: Proper clearing of OAuth state and PKCE parameters (AuthenticationFeature.swift:175-179)
  • Secure URLSession: TLS 1.2+, no caching/cookies for sensitive data (OAuthClient.swift:337-343)

⚠️ Security Concerns

  • Authorization Code Validation: Only basic length/empty checks (AuthenticationFeature.swift:398-403) - consider validating charset/format
  • Logging Sensitive Operations: Token operations still logged during "silent" refresh (AuthenticationFeature.swift:214-217)
  • Generic Crypto Error Messages: Could provide more specific guidance (AuthenticationFeature.swift:246-250)

🐛 Bug Analysis

Well-Handled Issues

  • Race Condition Prevention: Token refresh uses isRefreshing flag and task deduplication (MCPClientManager.swift:369-373)
  • Authentication State: Proper checks prevent duplicate auth sheets (ServerFeature.swift:463)
  • Error Recovery: Graceful fallback when keychain access fails (ServerFeature.swift:243-250)

🔧 Potential Issues

  • Token Refresh Timer: Starts on first access, could delay initial refresh checks (MCPClientManager.swift:304-307)
  • Metadata Rediscovery: Token refresh rediscovers metadata every time - performance impact (MCPClientManager.swift:395-397)
  • Reconnection Logic: Single attempt without exponential backoff (ServerFeature.swift:398-400)
  • Expired Token Edge Case: Should verify token isn't already expired before refresh window (MCPClientManager.swift:336)

Performance Considerations

Efficient Patterns

  • Concurrent Refresh Prevention: Reuses existing refresh tasks (MCPClientManager.swift:370-372)
  • Connection State Caching: Avoids unnecessary state checks
  • Async/Await Usage: Modern Swift concurrency throughout

💡 Optimization Opportunities

  • Metadata Caching: Cache authorization server metadata with TTL to reduce network calls
  • Connection Pooling: Consider reusing connections for multiple auth operations
  • Batch Token Refresh: Could batch multiple server refreshes
  • Configurable Timeouts: Hardcoded values could be configurable (MCPClientManager.swift:25-26)

📱 Swift Code Quality

Excellent Practices

  • TCA Integration: Clean reducer patterns with proper state isolation
  • Error Propagation: Comprehensive error typing and handling
  • Modern Swift: Effective use of async/await, actors, and Swift 6 features
  • Resource Management: Proper cleanup in deinit and cancellation handling
  • Dependencies Integration: Good use of TCA's dependency system

🔄 Improvement Opportunities

  • Code Duplication: Keychain access patterns repeated across files
  • Magic Numbers: Hardcoded timeouts and intervals could be constants
  • Error Specificity: Some generic error messages could be more helpful

🧪 Test Coverage Recommendations

Critical Test Scenarios

  1. Token Refresh Edge Cases: Network failures, invalid refresh tokens, concurrent refresh attempts
  2. Security Validation: State parameter tampering, CSRF protection, code injection attempts
  3. Race Conditions: Multiple authentication flows, concurrent token operations
  4. Error Recovery: Authentication failure scenarios, keychain access failures
  5. Network Issues: Metadata discovery failures, token exchange timeouts

📋 Recommendations

High Priority

  1. Add metadata caching with TTL to reduce repeated network calls during token refresh
  2. Implement exponential backoff for reconnection attempts
  3. Enhance authorization code validation beyond basic length checks
  4. Consider more specific error messages for crypto failures

Medium Priority

  1. Make timing constants configurable rather than hardcoded
  2. Reduce sensitive operation logging in production builds
  3. Add retry mechanisms for transient network failures
  4. Consider connection pooling for authentication operations

Low Priority

  1. Extract common keychain patterns to reduce duplication
  2. Add comprehensive logging configuration for debugging
  3. Document security assumptions and threat model

🎯 Overall Assessment

This is a well-implemented OAuth 2.0 solution with strong security foundations. The code demonstrates:

  • Solid security posture with proper PKCE and state validation
  • Modern Swift patterns using TCA and async/await effectively
  • Comprehensive error handling with user-friendly messaging
  • Good separation of concerns across authentication layers

The automatic token refresh mechanism is particularly well-designed, and the integration with TCA provides clean state management.

Recommendation: Approve with the suggested improvements for enhanced robustness and performance.


**🔗 **

@indragiek indragiek merged commit b2b6c68 into main Jul 3, 2025
3 checks passed
@indragiek indragiek deleted the oauth-bug-fixes branch July 3, 2025 17:59
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