Architecture Overview
OAuth Flow with PKCE
PKCE (RFC 7636) eliminates the need for client secrets in native/desktop apps. Rowboat uses S256 code challenge method for maximum security.
Authorization Flow Diagram
Core Components
1. Provider Configuration
Each OAuth provider has a configuration defining discovery and client registration:Provider Config Schema (providers.ts)
Provider Config Schema (providers.ts)
Location: Google Configuration:Fireflies Configuration (DCR):
core/src/auth/providers.tsSchema:2. OAuth Client (oauth-client.ts)
Discovery & Configuration
Discovery & Configuration
Discovery Process:
-
OIDC Discovery (issuer mode):
- Fetch
{issuer}/.well-known/openid-configuration - Extract
authorization_endpoint,token_endpoint, etc. - Cache configuration per
issuer:clientId
- Fetch
-
Static Configuration:
- Use pre-configured endpoints
- No discovery request needed
PKCE Generation
PKCE Generation
Purpose: Generate cryptographically secure code verifier and challengeImplementation:RFC 7636 Spec:
- Verifier: 43-128 characters, base64url-encoded
- Challenge: SHA-256 hash of verifier, base64url-encoded
- Method: S256 (SHA-256)
Token Exchange
Token Exchange
Process:Token Response:
- Capture authorization code from redirect
- Validate state matches (CSRF protection)
- Exchange code + verifier for tokens
- Parse and return tokens
Token Refresh
Token Refresh
Process:
- Check if access token is expired
- Use refresh token to get new access token
- Preserve existing scopes/refresh token if not returned
3. Dynamic Client Registration (DCR)
DCR (RFC 7591) allows apps to register OAuth clients programmatically, eliminating the need for pre-registered client IDs.
DCR Flow
DCR Flow
When to use DCR:Registration Response:
- Provider supports RFC 7591
- No pre-registered client ID available
- Want to avoid hardcoding client credentials
4. Token Storage (repo.ts)
Token Repository
Token Repository
Purpose: Securely persist OAuth tokens per providerStorage Location: Implementation:
~/.rowboat/auth/{provider}.jsonSchema:Complete OAuth Flow Example
Google OAuth Flow
Security Considerations
PKCE Security Benefits
PKCE Security Benefits
- No client secret: Cannot be extracted from app bundle
- One-time verifier: Different verifier for each authorization
- Challenge verification: Server validates verifier matches challenge
- MITM protection: Attacker cannot use intercepted code without verifier
State Parameter (CSRF Protection)
State Parameter (CSRF Protection)
Purpose: Prevent cross-site request forgery attacksHow it works:
- Generate random state before authorization
- Include state in authorization URL
- Provider returns state in callback
- Validate returned state matches original
Redirect URI Security
Redirect URI Security
Best practices:
- Use
http://localhost:{port}/callbackfor desktop apps - Choose random available port (8080-8090)
- Close local server after receiving callback
- Validate redirect URI matches registered URI
Token Storage Security
Token Storage Security
Current implementation:
- Tokens stored in
~/.rowboat/auth/as JSON files - File permissions: 600 (owner read/write only)
- No encryption (relies on OS file permissions)
- Use OS keychain (macOS Keychain, Windows Credential Manager)
- Encrypt tokens at rest
- Use secure enclave for token encryption keys
Error Handling
Common OAuth Errors
Common OAuth Errors
invalid_grant- Code expired, already used, or invalidinvalid_client- Client ID not recognizedinvalid_request- Missing required parametersaccess_denied- User declined authorizationserver_error- Provider had an internal error
Testing OAuth Flows
Manual Testing
Manual Testing
Code References
- OAuth Client:
core/src/auth/oauth-client.ts:1 - Provider Configs:
core/src/auth/providers.ts:53 - Token Repository:
core/src/auth/repo.ts - Token Types:
core/src/auth/types.ts - Client ID Provider:
core/src/auth/provider-client-id.ts