13 KiB
GIT-004A Phase 5B: Web OAuth Flow for Organization/Repository Selection
Status: 📋 PLANNED - Not Started
Priority: HIGH - Critical for organization repo access
Estimated Time: 6-8 hours
Dependencies: GIT-004A OAuth & Client Foundation (✅ Complete)
Executive Summary
Upgrade GitHub OAuth authentication from Device Flow to Web OAuth Flow to enable users to select which organizations and repositories they want to grant access to - matching the professional experience provided by Vercel, VS Code, and other modern developer tools.
Current State: Device Flow works for personal repositories but cannot show organization/repository selection UI.
Desired State: Web OAuth Flow with GitHub's native org/repo selection interface.
The Problem
Current Implementation (Device Flow)
User Experience:
1. User clicks "Connect GitHub Account"
2. Browser opens with 8-character code
3. User enters code on GitHub
4. Access granted to ALL repositories
5. ❌ No way to select specific orgs/repos
6. ❌ Organization repos return 403 errors
Technical Limitation:
- Device Flow is designed for devices without browsers (CLI tools)
- GitHub doesn't show org/repo selection UI in Device Flow
- Organization repositories require explicit app installation approval
- Users cannot self-service organization access
What Users Expect (Web OAuth Flow)
User Experience (like Vercel, VS Code):
1. User clicks "Connect GitHub Account"
2. Browser opens to GitHub OAuth page
3. ✅ GitHub shows: "Where would you like to install OpenNoodl?"
- Select organizations (dropdown/checkboxes)
- Select repositories (all or specific)
- Review permissions
4. User approves selection
5. Redirects back to OpenNoodl
6. ✅ Shows: "Connected to: Personal, Visual-Hive (3 repos)"
Benefits:
- ✅ Self-service organization access
- ✅ Granular repository control
- ✅ Clear permission review
- ✅ Professional UX
- ✅ No 403 errors on org repos
Solution Architecture
High-Level Flow
sequenceDiagram
participant User
participant OpenNoodl
participant Browser
participant GitHub
User->>OpenNoodl: Click "Connect GitHub"
OpenNoodl->>Browser: Open OAuth URL with state
Browser->>GitHub: Navigate to authorization page
GitHub->>User: Show org/repo selection UI
User->>GitHub: Select orgs/repos + Approve
GitHub->>Browser: Redirect to callback URL
Browser->>OpenNoodl: localhost:PORT/callback?code=...&state=...
OpenNoodl->>GitHub: Exchange code for token
GitHub->>OpenNoodl: Return access token
OpenNoodl->>User: Show "Connected to: [orgs]"
Key Components
1. Callback URL Handler (Electron Main Process)
- Registers IPC handler for
/github/callback - Validates OAuth state parameter (CSRF protection)
- Exchanges authorization code for access token
- Stores token + installation metadata
2. Web OAuth Flow (GitHubAuth service)
- Generates authorization URL with state
- Opens browser to GitHub OAuth page
- Listens for callback with code
- Handles success/error states
3. UI Updates (CredentialsSection)
- Shows installation URL instead of device code
- Displays connected organizations
- Repository count per organization
- Disconnect clears all installations
Technical Requirements
Prerequisites
✅ Already Complete:
- GitHub App registered (client ID exists)
- OAuth service layer built
- Token storage implemented
- UI integration complete
- Git authentication working
❌ New Requirements:
- Callback URL handler in Electron main process
- OAuth state management (CSRF protection)
- Installation metadata storage
- Organization/repo list display
GitHub App Configuration
Required Settings:
- Callback URL:
http://127.0.0.1:3000/github/callback(or dynamic port) - Permissions: Already configured (Contents: R/W, etc.)
- Installation Type: "User authorization" (not "Server-to-server")
Client ID: Already exists (Iv1.b507a08c87ecfe98)
Client Secret: Need to add (secure storage)
Implementation Phases
Phase 1: Callback Handler (2 hours)
Goal: Handle OAuth redirects in Electron
Tasks:
- Add IPC handler for
/github/callbackroute - Implement OAuth state generation/validation
- Create token exchange logic
- Store installation metadata
- Test callback flow manually
Files:
packages/noodl-editor/src/main/github-oauth-handler.ts(new)packages/noodl-editor/src/main/main.js(register handler)
Phase 2: Web OAuth Flow (2 hours)
Goal: Replace Device Flow with Web Flow
Tasks:
- Update
GitHubAuth.tswith web flow methods - Generate authorization URL with scopes + state
- Open browser to authorization URL
- Listen for callback completion
- Update types for installation data
Files:
packages/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.ts
Phase 3: UI Integration (1-2 hours)
Goal: Show org/repo selection results
Tasks:
- Update "Connect" button to use web flow
- Display connected organizations
- Show repository count per org
- Add loading states during OAuth
- Handle error states gracefully
Files:
packages/noodl-editor/src/editor/src/views/panels/VersionControlPanel/components/GitProviderPopout/sections/CredentialsSection.tsx
Phase 4: Testing & Polish (1-2 hours)
Goal: Verify full flow works end-to-end
Tasks:
- Test personal repo access
- Test organization repo access
- Test multiple org selection
- Test disconnect/reconnect
- Test error scenarios
- Update documentation
Success Criteria
Functional Requirements
- User can initiate OAuth from OpenNoodl
- GitHub shows organization/repository selection UI
- User can select specific orgs and repos
- After approval, user redirected back to OpenNoodl
- Access token works for selected orgs/repos
- UI shows which orgs are connected
- Git operations work with selected repos
- Disconnect clears all connections
- No 403 errors on organization repos
Non-Functional Requirements
- OAuth state prevents CSRF attacks
- Tokens stored securely (encrypted)
- Installation metadata persisted
- Error messages are user-friendly
- Loading states provide feedback
- Works on macOS, Windows, Linux
User Stories
Story 1: Connect Personal Account
As a solo developer
I want to connect my personal GitHub account
So that I can use Git features without managing tokens
Acceptance Criteria:
- Click "Connect GitHub Account"
- See organization selection UI (even if only "Personal")
- Select personal repos
- See "Connected to: Personal"
- Git push/pull works
Story 2: Connect Organization Account
As a team developer
I want to connect my organization's repositories
So that I can collaborate on team projects
Acceptance Criteria:
- Click "Connect GitHub Account"
- See dropdown: "Personal, Visual-Hive, Acme Corp"
- Select "Visual-Hive"
- Choose "All repositories" or specific repos
- See "Connected to: Visual-Hive (5 repos)"
- Git operations work on org repos
- No 403 errors
Story 3: Multiple Organizations
As a contractor
I want to connect multiple client organizations
So that I can work on projects across organizations
Acceptance Criteria:
- Click "Connect GitHub Account"
- Select multiple orgs: "Personal, Client-A, Client-B"
- See "Connected to: Personal, Client-A, Client-B"
- Switch between projects from different orgs
- Git operations work for all
Security Considerations
OAuth State Parameter
Purpose: Prevent CSRF attacks
Implementation:
// Generate random state before redirecting
const state = crypto.randomBytes(32).toString('hex');
sessionStorage.set('github_oauth_state', state);
// Validate on callback
if (receivedState !== sessionStorage.get('github_oauth_state')) {
throw new Error('Invalid OAuth state');
}
Client Secret Storage
⚠️ IMPORTANT: Client secret must be securely stored
Options:
- Environment variable (development)
- Electron SafeStorage (production)
- Never commit to Git
- Never expose to renderer process
Token Storage
Already Implemented: electron-store with encryption
Known Limitations
1. Port Conflicts
Issue: Callback URL uses fixed port (e.g., 3000)
Mitigation:
- Try multiple ports (3000, 3001, 3002, etc.)
- Show error if all ports busy
- Document how to change in settings
2. Firewall Issues
Issue: Some corporate firewalls block localhost callbacks
Mitigation:
- Provide PAT fallback option
- Document firewall requirements
- Consider alternative callback methods
3. Installation Scope Changes
Issue: User might modify org/repo access on GitHub later
Mitigation:
- Validate token before each Git operation
- Show clear error if access revoked
- Easy reconnect flow
Migration Strategy
Backward Compatibility
Current Users (Device Flow):
- Keep working with existing tokens
- Show "Upgrade to Web OAuth" prompt
- Optional migration (not forced)
New Users:
- Only see Web OAuth option
- Device Flow removed from UI
- Cleaner onboarding
Migration Path
// Check token source
if (token.source === 'device_flow') {
// Show upgrade prompt
showUpgradePrompt({
title: 'Upgrade GitHub Connection',
message: 'Get organization access with one click',
action: 'Reconnect with Organizations'
});
}
Testing Strategy
Manual Testing Checklist
Setup:
- GitHub App has callback URL configured
- Client secret available in environment
- Test GitHub account has access to orgs
Personal Repos:
- Connect personal account
- Select personal repos
- Verify Git push works
- Verify Git pull works
- Disconnect and reconnect
Organization Repos:
- Connect with org access
- Select specific org
- Choose repos (all vs. specific)
- Verify Git operations work
- Test 403 is resolved
- Verify other org members can do same
Error Cases:
- Cancel during GitHub approval
- Network error during callback
- Invalid state parameter
- Expired authorization code
- Port conflict on callback
- Firewall blocks callback
Automated Testing
Unit Tests:
describe('GitHubWebAuth', () => {
it('generates valid authorization URL', () => {
const url = GitHubWebAuth.generateAuthUrl();
expect(url).toContain('client_id=');
expect(url).toContain('state=');
});
it('validates OAuth state', () => {
const state = 'abc123';
expect(() => GitHubWebAuth.validateState(state, 'wrong')).toThrow();
});
it('exchanges code for token', async () => {
const token = await GitHubWebAuth.exchangeCode('test_code');
expect(token.access_token).toBeDefined();
});
});
Documentation Updates
User-Facing Docs
New Guide: "Connecting GitHub Organizations"
- How org/repo selection works
- Step-by-step with screenshots
- Troubleshooting common issues
- How to modify access later
Update Existing: "Git Setup Guide"
- Replace Device Flow instructions
- Add org selection section
- Update screenshots
Developer Docs
New: docs/github-web-oauth.md
- Technical implementation details
- Security considerations
- Testing guide
Comparison: Device Flow vs. Web OAuth Flow
| Feature | Device Flow | Web OAuth Flow |
|---|---|---|
| User Experience | Code entry | ✅ Click + Select |
| Org/Repo Selection | ❌ No | ✅ Yes |
| Organization Access | ❌ Manual | ✅ Automatic |
| Setup Complexity | Simple | Medium |
| Security | Good | ✅ Better (state) |
| Callback Requirements | None | Localhost server |
| Firewall Compatibility | ✅ Excellent | Good |
| Professional UX | Basic | ✅ Professional |
Verdict: Web OAuth Flow is superior for OpenNoodl's use case.
Timeline Estimate
| Phase | Time Estimate | Dependencies |
|---|---|---|
| Phase 1: Callback Handler | 2 hours | None |
| Phase 2: Web OAuth Flow | 2 hours | Phase 1 |
| Phase 3: UI Integration | 1-2 hours | Phase 2 |
| Phase 4: Testing & Polish | 1-2 hours | Phase 3 |
| Total | 6-8 hours |
Suggested Schedule:
- Day 1 Morning: Phase 1 (Callback Handler)
- Day 1 Afternoon: Phase 2 (Web OAuth Flow)
- Day 2 Morning: Phase 3 (UI Integration)
- Day 2 Afternoon: Phase 4 (Testing & Polish)
Next Steps
- Review this document with team
- Get GitHub App client secret from settings
- Configure callback URL in GitHub App settings
- Toggle to Act mode and begin Phase 1
- Follow IMPLEMENTATION-STEPS.md for detailed guide
Related Documentation
- TECHNICAL-APPROACH.md - Detailed architecture
- IMPLEMENTATION-STEPS.md - Step-by-step guide
- CHANGELOG.md - Progress tracking
- GIT-004A-CHANGELOG.md - Foundation work
Last Updated: 2026-01-09
Author: Cline AI Assistant
Reviewers: [Pending]