mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 22:03:45 +00:00
- Add /login and /logout commands for OAuth flow - OAuth tokens stored in ~/.pi/agent/oauth.json with 0600 permissions - Auto-refresh tokens when expired (5min buffer) - Priority: OAuth > ANTHROPIC_OAUTH_TOKEN env > ANTHROPIC_API_KEY env - Fix model selector async loading and re-render - Add bracketed paste support to Input component for long codes - Update README.md with OAuth documentation - Add implementation docs and testing checklist
6.6 KiB
6.6 KiB
OAuth Implementation Summary
Status: Phase 1 (Anthropic OAuth) - Complete ✓
Implementation of OAuth2 authentication support for Anthropic (Claude Pro/Max) has been completed according to the plan in oauth-plan.md.
What Was Implemented
New Files Created
-
src/oauth/storage.ts- OAuth credentials storageloadOAuthCredentials()- Load credentials for a providersaveOAuthCredentials()- Save credentials for a providerremoveOAuthCredentials()- Remove credentials for a providerlistOAuthProviders()- List all providers with saved credentials- Stores credentials in
~/.pi/agent/oauth.jsonwith0o600permissions
-
src/oauth/anthropic.ts- Anthropic OAuth flowloginAnthropic()- Device code flow implementation with PKCErefreshAnthropicToken()- Refresh expired OAuth tokens- Uses Anthropic's OAuth endpoints with proper client ID and scopes
-
src/oauth/index.ts- OAuth provider abstractiongetOAuthProviders()- List available OAuth providerslogin()- Generic login function (routes to provider-specific implementation)logout()- Generic logout functionrefreshToken()- Refresh token for any providergetOAuthToken()- Get token with automatic refresh if expired
-
src/tui/oauth-selector.ts- TUI component for provider selection- Interactive selector for login/logout operations
- Shows available providers and their status
- Keyboard navigation (arrow keys, Enter, Escape)
Modified Files
-
src/model-config.ts- Updated
getApiKeyForModel()to be async and check OAuth credentials - Resolution order for Anthropic:
ANTHROPIC_OAUTH_TOKENenv var- OAuth storage (auto-refresh if needed)
ANTHROPIC_API_KEYenv var
- Updated
getAvailableModels()to be async
- Updated
-
src/main.ts- Updated all calls to
getApiKeyForModel()andgetAvailableModels()to await them - Transport's
getApiKeycallback is already async, just needed to await the helper
- Updated all calls to
-
src/tui/tui-renderer.ts- Added
/loginand/logoutslash commands - Implemented
showOAuthSelector()- shows provider selector and handles auth flow - Implemented
hideOAuthSelector()- restores editor after auth - Updated
handleInput()in editor to handle new commands - Added OAuth selector field to class
- Updated API key validation to use async
getApiKeyForModel()
- Added
-
src/tui/model-selector.ts- Updated
loadModels()to be async - Changed initialization to await model loading
- Updated
-
README.md- Added "OAuth Authentication (Optional)" section after API Keys
- Documented
/loginand/logoutslash commands - Explained benefits of OAuth (free models, no key management, auto-refresh)
How It Works
User Flow
- User types
/loginin the interactive session - Provider selector appears (currently only shows Anthropic)
- User selects provider with arrow keys and Enter
- Browser opens to Anthropic's OAuth authorization page
- User authorizes the app and copies the authorization code
- User pastes code in the terminal input
- Tokens are exchanged and saved to
~/.pi/agent/oauth.json - User can now use Claude models without API keys
Technical Flow
- Login: Authorization Code Flow with PKCE
- Generate PKCE verifier and challenge
- Build auth URL with
state=verifier - User authorizes in browser, gets code in format
code#state - Exchange code for tokens using JSON API
- Save tokens to storage
- Token Usage: Check expiry → auto-refresh if needed → return access token
- API Key Resolution: OAuth tokens checked before falling back to API keys
- Logout: Remove credentials from storage file
OAuth Flow Details (from opencode-anthropic-auth)
Based on SST's opencode implementation:
- Redirect URI:
https://console.anthropic.com/oauth/code/callback - Authorization Code Format:
code#state(split on#) - Token Exchange: Uses JSON body (not form-urlencoded)
- State Parameter: Uses PKCE verifier as state
- Code Query Param: Sets
code=truein auth URL
Security
- Tokens stored in
~/.pi/agent/oauth.jsonwith0o600permissions (owner read/write only) - PKCE used for authorization code flow (prevents authorization code interception)
- 5-minute buffer before token expiry to prevent edge cases
- Tokens never logged (would need to add
[REDACTED]in debug output if we add logging)
Testing Recommendations
-
Happy Path
/login→ authorize → verify token saved- Use Claude models → verify OAuth token used
/logout→ verify credentials removed
-
Error Cases
- Invalid authorization code
- Network errors during token exchange
- Expired refresh token
-
Fallback Behavior
- OAuth token expires → auto-refresh
- Refresh fails → fall back to API key
- No OAuth, no API key → show helpful error
-
Integration
- Test with
ANTHROPIC_OAUTH_TOKENenv var (manual token) - Test with saved OAuth credentials (auto-refresh)
- Test with
ANTHROPIC_API_KEYfallback - Test switching between OAuth and API key models
- Test with
Next Steps (Phase 2 - Future)
Phase 2 (GitHub Copilot OAuth) is planned but not implemented. See oauth-plan.md for details.
Key differences from Anthropic:
- Two-step token exchange (GitHub OAuth → Copilot API token)
- Custom headers required for every request
- Shorter token lifespan (~30 min)
- More complex implementation
Success Criteria (Phase 1) ✓
- Plan documented
pi loginsuccessfully authenticates with Anthropic- Tokens saved to
oauth.jsonwith correct permissions - Models work with OAuth tokens (detected as
sk-ant-oat-...) - Token auto-refresh works on expiry
pi logoutremoves credentials- Falls back to API keys when OAuth not available
- No breaking changes for existing users
- TypeScript compilation passes
- Linting passes
- README updated with OAuth documentation
Files Summary
New Files (4):
src/oauth/storage.ts(2,233 bytes)src/oauth/anthropic.ts(3,225 bytes)src/oauth/index.ts(2,662 bytes)src/tui/oauth-selector.ts(3,386 bytes)
Modified Files (5):
src/model-config.ts- Async API key resolution with OAuthsrc/main.ts- Async updates for model/key lookupssrc/tui/tui-renderer.ts- Login/logout commands and UIsrc/tui/model-selector.ts- Async model loadingREADME.md- OAuth documentation
Total Changes:
- ~11,506 bytes of new code
- Multiple async function updates
- Documentation updates
- Zero breaking changes