8.0 KiB
CHANGELOG: GIT-004A Phase 5B - Web OAuth Flow
Overview
Implemented GitHub Web OAuth Flow to replace Device Flow, enabling users to select which organizations and repositories to grant access to during authentication.
Status: ❌ FAILED - See FAILURE-REPORT.md
Date Attempted: January 9-10, 2026
Time Spent: ~4 hours
Result: OAuth completes but callback handling broken - debug logs never appear
See detailed failure analysis: FAILURE-REPORT.md
Changes Made
1. Main Process OAuth Handler ✅
File: packages/noodl-editor/src/main/github-oauth-handler.ts (NEW)
- Created
GitHubOAuthCallbackHandlerclass - Implements localhost HTTP server on ports 3000-3004 (with fallback)
- Handles
/github/callbackroute for OAuth redirects - CSRF protection via state parameter
- Exchanges authorization code for access token
- Fetches user info and installation data from GitHub API
- Sends results to renderer process via IPC
- Beautiful success/error pages for browser callback
Key Features:
- Port fallback mechanism (tries 3000-3004)
- Secure state validation (5-minute expiration)
- Proper error handling with user-friendly messages
- Clean IPC communication with renderer
2. Main Process Integration ✅
File: packages/noodl-editor/src/main/main.js
- Imported
initializeGitHubOAuthHandlers - Registered OAuth handlers in
app.on('ready')event - IPC channels:
github-oauth-start,github-oauth-stop - IPC events:
github-oauth-complete,github-oauth-error
3. GitHub Auth Service Upgrade ✅
File: packages/noodl-editor/src/editor/src/services/github/GitHubAuth.ts
Added:
startWebOAuthFlow()- New Web OAuth implementation- Communicates with main process via IPC
- Opens browser to GitHub authorization page
- Waits for callback with 5-minute timeout
- Saves token + installations to storage
- Proper cleanup of IPC listeners
Deprecated:
startDeviceFlow()- Marked as deprecated- Now forwards to
startWebOAuthFlow()for backward compatibility
Removed Dependencies:
- No longer depends on
@octokit/auth-oauth-device - Uses native Electron IPC instead
4. Type Definitions Enhanced ✅
File: packages/noodl-editor/src/editor/src/services/github/GitHubTypes.ts
Added:
GitHubInstallationinterface- Installation ID
- Account info (login, type, avatar)
- Repository selection type
- List of repositories (if selected)
Updated:
StoredGitHubAuthinterface now includesinstallations?: GitHubInstallation[]
5. Token Store Enhanced ✅
File: packages/noodl-editor/src/editor/src/services/github/GitHubTokenStore.ts
Updated:
saveToken()now accepts optionalinstallationsparameter- Logs connected organizations when saving
- Added
getInstallations()method to retrieve stored installations
6. UI Updated ✅
File: packages/noodl-editor/src/editor/src/views/panels/VersionControlPanel/components/GitProviderPopout/sections/CredentialsSection.tsx
Changed:
handleConnect()now callsGitHubAuth.startWebOAuthFlow()instead ofstartDeviceFlow()- UI flow remains identical for users
- Progress messages update during OAuth flow
- Error handling unchanged
Technical Implementation Details
OAuth Flow Sequence
1. User clicks "Connect GitHub Account" button
↓
2. Renderer calls GitHubAuth.startWebOAuthFlow()
↓
3. Renderer sends IPC 'github-oauth-start' to main process
↓
4. Main process starts localhost HTTP server (port 3000-3004)
↓
5. Main process generates OAuth state (CSRF token)
↓
6. Main process returns authorization URL to renderer
↓
7. Renderer opens browser to GitHub OAuth page
↓
8. GitHub shows: "Where would you like to install OpenNoodl?"
→ User selects organizations
→ User selects repositories (all or specific)
→ User reviews permissions
↓
9. User approves → GitHub redirects to localhost:PORT/github/callback?code=XXX&state=YYY
↓
10. Main process validates state (CSRF check)
↓
11. Main process exchanges code for access token
↓
12. Main process fetches user info from GitHub API
↓
13. Main process fetches installation info (orgs/repos)
↓
14. Main process sends success to renderer via IPC 'github-oauth-complete'
↓
15. Renderer saves token + installations to encrypted storage
↓
16. UI shows "Connected as USERNAME"
↓
17. Main process closes HTTP server
Security Features
-
CSRF Protection
- Random 32-byte state parameter
- 5-minute expiration window
- Validated on callback
-
Secure Token Storage
- Tokens encrypted via electron-store
- Installation data included in encrypted storage
- OS-level encryption (Keychain/Credential Manager)
-
Localhost Only
- Server binds to
127.0.0.1(not0.0.0.0) - Only accepts connections from localhost
- Server auto-closes after auth complete
- Server binds to
-
Error Handling
- Timeout after 5 minutes
- Proper IPC cleanup
- User-friendly error messages
Backward Compatibility
startDeviceFlow()still exists (deprecated)- Forwards to
startWebOAuthFlow()internally - Existing code continues to work
- PAT authentication unchanged
Benefits
For Users
-
Better Permission Control
- Select which organizations to connect
- Choose all repositories or specific ones
- Review permissions before granting
-
No More 403 Errors
- Proper organization repository access
- Installations grant correct permissions
- Works with organization private repos
-
Professional UX
- Matches Vercel/VS Code OAuth experience
- Clean browser-based flow
- No code copying required
For Developers
-
Cleaner Implementation
- No polling required
- Direct callback handling
- Standard OAuth 2.0 flow
-
Installation Metadata
- Know which orgs/repos user granted access to
- Can display connection status
- Future: repo selection in UI
-
Maintainable
- Standard patterns
- Well-documented
- Proper error handling
Testing Checklist
- Test OAuth with personal repos
- Test OAuth with organization repos
- Test org/repo selection UI on GitHub
- Verify no 403 errors on org repos
- Test disconnect and reconnect flows
- Test PAT authentication (should still work)
- Test error scenarios (timeout, user denies, etc.)
- Verify token encryption
- Test port fallback (3000-3004)
- Verify installation data is saved
Files Modified
Created
packages/noodl-editor/src/main/github-oauth-handler.ts
Modified
packages/noodl-editor/src/main/main.jspackages/noodl-editor/src/editor/src/services/github/GitHubAuth.tspackages/noodl-editor/src/editor/src/services/github/GitHubTypes.tspackages/noodl-editor/src/editor/src/services/github/GitHubTokenStore.tspackages/noodl-editor/src/editor/src/views/panels/VersionControlPanel/components/GitProviderPopout/sections/CredentialsSection.tsx
Next Steps
Phase 2: UI Enhancement (Future Work)
- Display connected organizations in UI
- Show repository count per organization
- Add "Manage Access" button to update permissions
Phase 3: Cleanup (Future Work)
- Remove
@octokit/auth-oauth-devicedependency - Deprecate
GitHubOAuthService.ts - Update documentation
Phase 4: Testing (Required Before Merge)
- Manual testing with personal account
- Manual testing with organization account
- Edge case testing (timeouts, errors, etc.)
- Cross-platform testing (macOS, Windows)
Notes
- GitHub App credentials already exist (
Iv23lib1WdrimUdyvZui) - Client secret stored in environment variable
- Callback URL registered:
http://localhost:3000/github/callback - Port range 3000-3004 for fallback
- Installation data saved but not yet displayed in UI
References
- GitHub OAuth Web Flow: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
- GitHub Installations API: https://docs.github.com/en/rest/apps/installations
- Electron IPC: https://www.electronjs.org/docs/latest/api/ipc-renderer