OAuth Authenticator Developer Guide
Comprehensive OAuth 2.0 implementation with two-level architecture for secure third-party authentication. Configure authenticators for Gmail, Slack, GitHub, and custom services with automated token management and enterprise-grade security.
Table of Contents
🏗️ System Overview
FiberWise's OAuth Authenticator system provides a comprehensive two-level OAuth 2.0 architecture that separates developer configuration from user authentication:
- Developer Level: Configure OAuth authenticators using CLI or Web interface
- User Level: End users connect their personal accounts through secure OAuth flows
🔒 Enterprise Security: Automatic token management, refresh handling, encrypted storage, and compliance-ready audit trails
System Architecture
graph TB subgraph "Developer Level" CLI[CLI Tool] WebUI[Web Interface] Config[JSON Config Files] end subgraph "FiberWise Platform" API[OAuth Authenticator API] DB[(OAuth Authenticators DB)] AuthService[Authentication Service] end subgraph "User Level" UserUI[User Settings Page] OAuth[OAuth Flow] Tokens[(User Tokens)] end subgraph "External Providers" Google[Google OAuth] Microsoft[Microsoft OAuth] GitHub[GitHub OAuth] Custom[Custom Providers] end CLI --> API WebUI --> API Config --> CLI API --> DB API --> AuthService UserUI --> AuthService AuthService --> OAuth OAuth --> Tokens OAuth --> Google OAuth --> Microsoft OAuth --> GitHub OAuth --> Custom style DB fill:#e1f5fe style Tokens fill:#f3e5f5 style AuthService fill:#e8f5e8
🔄 OAuth Flow Architecture
Complete OAuth Sequence
sequenceDiagram participant Dev as Developer participant CLI as FiberWise CLI participant Web as Web Interface participant API as OAuth API participant DB as Database participant User as End User participant Auth as Auth Service participant Provider as OAuth Provider Note over Dev,DB: Phase 1: Developer Setup alt CLI Path Dev->>CLI: fiber register-authenticator CLI->>API: POST /api/v1/oauth/authenticators else Web Path Dev->>Web: Settings → OAuth Authenticators Web->>API: POST /api/v1/oauth/authenticators end API->>DB: Store authenticator config Note over User,Provider: Phase 2: User Authentication User->>Auth: Click "Connect Google" Auth->>Provider: Redirect to OAuth authorize Provider->>User: Authorization prompt User->>Provider: Grant permission Provider->>Auth: Authorization code Auth->>Provider: Exchange code for tokens Provider->>Auth: Access & refresh tokens Auth->>DB: Store user tokens Auth->>User: Connection successful
Database Schema Architecture
erDiagram oauth_authenticators { int id PK string authenticator_id UK string authenticator_name string authenticator_type string client_id string client_secret string redirect_uri string authorize_url string token_url json scopes json configuration boolean is_active datetime created_at datetime updated_at } oauth_token_grants { string grant_id PK int user_id FK string authenticator_id FK string access_token string refresh_token string token_type datetime expires_at json scopes boolean is_revoked datetime created_at datetime updated_at } user_app_oauth_authentications { string auth_id PK int user_id FK string app_id FK string authenticator_id FK string grant_id FK string auth_status boolean is_active datetime created_at datetime last_used_at } oauth_sessions { int id PK string session_id UK string authenticator_name int user_id FK string state_token string redirect_uri json scopes datetime created_at datetime expires_at } oauth_authenticators ||--o{ oauth_token_grants : "authenticator_id" oauth_authenticators ||--o{ user_app_oauth_authentications : "authenticator_id" oauth_token_grants ||--|| user_app_oauth_authentications : "grant_id" oauth_sessions }o--|| oauth_authenticators : "references"
🚀 Getting Started
Prerequisites
- ✅ FiberWise CLI installed and configured
- ✅ Application created and registered
- ✅ OAuth credentials from your chosen authenticator(s)
Two Development Paths
Choose the path that fits your workflow:
CLI Path
Command-line interface for developers who prefer terminal workflows
- JSON configuration files
- Script automation
- Version control friendly
Web Interface
Browser-based configuration with smart forms and validation
- Visual interface
- Auto-population
- Real-time validation
💻 Path 1: Command Line Interface
Step 1: Create Authenticator Configuration
Create JSON configuration files for each OAuth authenticator:
Google Authenticator Configuration
{
"name": "Google",
"authenticator_type": "google",
"client_id": "123456789-abcdef.apps.googleusercontent.com",
"client_secret": "GOCSPX-your-secret-here",
"scopes": [
"openid",
"profile",
"email",
"https://www.googleapis.com/auth/gmail.readonly"
],
"redirect_uri": "https://your-app.com/auth/callback/google",
"authorize_url": "https://accounts.google.com/o/oauth2/v2/auth",
"token_url": "https://oauth2.googleapis.com/token"
}
Microsoft Authenticator Configuration
{
"name": "Microsoft",
"authenticator_type": "microsoft",
"client_id": "12345678-1234-1234-1234-123456789abc",
"client_secret": "your-microsoft-secret",
"scopes": [
"User.Read",
"Mail.Read",
"Calendars.Read"
],
"redirect_uri": "https://your-app.com/auth/callback/microsoft",
"authorize_url": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
"token_url": "https://login.microsoftonline.com/common/oauth2/v2.0/token"
}
Step 2: Register Authenticator via CLI
# Navigate to your app directory
cd /path/to/your-app
# Register the authenticator
fiber app oauth register-authenticator \
--authenticator-config ./google-authenticator.json \
--to-instance production
# Verify registration
fiber app oauth list-authenticators --to-instance production
Step 3: Advanced CLI Usage
# Register for specific app directory
fiber app oauth register-authenticator \
--authenticator-config ./microsoft-authenticator.json \
--app-dir ./my-email-app \
--to-instance staging
# Delete an authenticator
fiber app oauth delete-authenticator google-auth-id \
--to-instance production
# List all authenticators for an app
fiber app oauth list-authenticators \
--app-dir ./my-app \
--to-instance development
# Environment-specific configurations
fiber app oauth register-authenticator \
--authenticator-config ./dev-google.json \
--to-instance development
🌐 Path 2: Web Interface (Planned)
Access OAuth Settings
- Open FiberWise platform in your browser
- Navigate to Settings → OAuth Authenticators
- Click the "Manage Authenticators" tab
Add New Authenticator
- Click "Add Authenticator" button
- Name: Display name (e.g., "Google")
- Type: Select from dropdown (auto-populates URLs)
- Client ID: From your OAuth provider console
- Client Secret: From your OAuth provider console
- Scopes: Comma-separated permissions
Smart Form Features
- Auto-Population: Selecting "Google" automatically fills OAuth URLs
- Template Scopes: Common scope combinations for each provider
- Validation: Real-time field validation
- Error Handling: Clear error messages and suggestions
Web Interface Flow
flowchart LR A[Select Provider Type] --> B{Is Common Provider?} B -->|Yes| C[Auto-fill URLs & Scopes] B -->|No| D[Manual Entry Required] C --> E[Enter Credentials] D --> E E --> F[Validate Form] F --> G{Valid?} G -->|No| H[Show Validation Errors] G -->|Yes| I[Register Authenticator] H --> E I --> J[Success Message] style C fill:#e8f5e8 style I fill:#e1f5fe style H fill:#ffebee
🔧 Provider-Specific Setup Guides
Google OAuth Setup
Google Cloud Console
Go to Google Cloud Console
- Create/select project
- Enable APIs (Gmail, Calendar, etc.)
- Create OAuth 2.0 credentials
- Add redirect URI:
https://your-app.com/auth/callback/google
CLI Registration
fiber register-authenticator google \
--client-id="123456789-abcdef.apps.googleusercontent.com" \
--client-secret="GOCSPX-your-secret" \
--scopes="profile,email,https://www.googleapis.com/auth/gmail.readonly"
Common Google Scopes
Scope | Description | Use Case |
---|---|---|
profile |
Basic profile information | User identification |
email |
Email address | User contact info |
gmail.readonly |
Read Gmail messages | Email analysis, search |
gmail.modify |
Modify Gmail messages | Email management, labels |
calendar |
Access calendar events | Scheduling, reminders |
Microsoft OAuth Setup
Azure Portal
Go to Azure Portal
- Register application in Azure AD
- Configure API permissions (Microsoft Graph)
- Add redirect URI:
https://your-app.com/auth/callback/microsoft
CLI Registration
fiber register-authenticator microsoft \
--client-id="12345678-1234-1234-1234-123456789abc" \
--client-secret="your-secret" \
--scopes="User.Read,Mail.Read,Calendars.Read"
Common Microsoft Scopes
Scope | Description | Use Case |
---|---|---|
User.Read |
Read user profile | User identification |
Mail.Read |
Read user's mail | Email analysis |
Mail.ReadWrite |
Read and write mail | Email management |
Calendars.Read |
Read calendars | Schedule viewing |
Files.Read |
Read user's files | Document access |
GitHub OAuth Setup
GitHub Developer Settings
Go to GitHub Settings > Developer settings > OAuth Apps
- Create new OAuth app
- Set Authorization callback URL:
https://your-app.com/auth/callback/github
CLI Registration
fiber register-authenticator github \
--client-id="your-github-client-id" \
--client-secret="your-github-client-secret" \
--scopes="user,repo,read:org"
Custom Provider Setup
For OAuth 2.0 providers not in the template list:
{
"name": "Custom Provider",
"authenticator_type": "custom",
"client_id": "your-custom-client-id",
"client_secret": "your-custom-client-secret",
"scopes": ["custom:scope1", "custom:scope2"],
"authorize_url": "https://custom-provider.com/oauth/authorize",
"token_url": "https://custom-provider.com/oauth/token",
"redirect_uri": "https://your-app.com/auth/callback/custom"
}
🔄 User Authentication Flow
After developers register authenticators, end users can connect their accounts:
graph TD A[User Opens App] --> B[Navigate to Settings] B --> C[OAuth Authenticators Page] C --> D[Connections Tab] D --> E{Authenticator Available?} E -->|Yes| F[Click Connect Button] E -->|No| G[Contact Developer] F --> H[Redirect to Provider] H --> I[User Authorizes] I --> J[Return to FiberWise] J --> K[Store Tokens] K --> L[Show Success Message] L --> M[App Can Access APIs] style K fill:#e8f5e8 style M fill:#e1f5fe style G fill:#ffebee
Token Lifecycle Management
stateDiagram-v2 [*] --> AuthenticatorConfigured: CLI register-authenticator AuthenticatorConfigured --> AuthInitiated: User clicks connect AuthInitiated --> AuthorizationPending: Redirect to authenticator AuthorizationPending --> TokensReceived: User authorizes TokensReceived --> TokensStored: Store in database TokensStored --> Active: Connection active Active --> TokenExpired: Time passes TokenExpired --> RefreshAttempt: Auto refresh RefreshAttempt --> Active: Success RefreshAttempt --> Revoked: Refresh failed Active --> UserRevoked: User disconnects UserRevoked --> Revoked Revoked --> [*]: Connection removed note right of Active: Tokens used for API calls note right of RefreshAttempt: Automatic background process
🔍 API Reference
Register Authenticator
POST /api/v1/oauth/authenticators
Content-Type: application/json
{
"name": "Google",
"authenticator_type": "google",
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"scopes": ["profile", "email"],
"authorize_url": "https://accounts.google.com/o/oauth2/v2/auth",
"token_url": "https://oauth2.googleapis.com/token",
"redirect_uri": "https://your-app.com/auth/callback/google",
"app_id": "your-app-id"
}
List Authenticators
GET /api/v1/oauth/authenticators?app_id=your-app-id
Delete Authenticator
DELETE /api/v1/oauth/authenticators/{authenticator_id}
Frontend Integration
// Import FiberWise SDK
import FiberWise from 'fiberwise';
// Initialize SDK
const fiber = new FiberWise({
baseUrl: 'https://api.fiberwise.ai/api/v1',
appId: 'your-app-id'
});
// OAuth Integration using FiberWise SDK
class OAuthManager {
constructor() {
this.credentials = fiber.credentials;
}
// Connect to Gmail
async connectGmail() {
try {
await this.credentials.connectAuthenticator('google', {
returnTo: '/settings'
});
} catch (error) {
console.error('Gmail connection failed:', error);
}
}
// Check Gmail connection status
async isGmailConnected() {
try {
return await this.credentials.isConnected('google');
} catch (error) {
console.error('Error checking Gmail connection:', error);
return false;
}
}
// Connect to other providers
async connectSlack() {
await this.credentials.connectAuthenticator('slack', {
returnTo: '/dashboard'
});
}
async connectGitHub() {
await this.credentials.connectAuthenticator('github');
}
// List available authenticators
async getAvailableProviders() {
try {
return await this.credentials.listAuthenticators({
includeDisabled: false
});
} catch (error) {
console.error('Error listing authenticators:', error);
return [];
}
}
// Disconnect from provider
async disconnect(authenticatorId) {
try {
await this.credentials.revokeConnection(authenticatorId);
console.log(`Disconnected from ${authenticatorId}`);
} catch (error) {
console.error(`Failed to disconnect:`, error);
}
}
// Check if page is OAuth callback
isOAuthCallback(authenticatorId) {
return this.credentials.isConnectionCallback(authenticatorId);
}
}
// Usage
const oauth = new OAuthManager();
// Event handlers
document.getElementById('connect-gmail').addEventListener('click', () => {
oauth.connectGmail();
});
document.getElementById('connect-slack').addEventListener('click', () => {
oauth.connectSlack();
});
// Check connections on page load
async function checkConnections() {
const providers = ['google', 'slack', 'github'];
for (const provider of providers) {
const connected = await oauth.credentials.isConnected(provider);
console.log(`${provider}: ${connected ? 'Connected' : 'Not connected'}`);
}
}
Backend Agent Integration
# Python agent using OAuth credentials
from fiberwise import Agent
class EmailProcessorAgent(Agent):
async def process_user_email(self, user_context):
# OAuth credentials automatically injected
gmail_service = await self.get_oauth_authenticator('gmail')
# Fetch recent emails
emails = await gmail_service.get_recent_emails(limit=10)
# Process with LLM
summary = await self.llm.generate(
f"Summarize these emails: {emails}"
)
return {
"email_count": len(emails),
"summary": summary
}
🔒 Security Best Practices
🔐 Authenticator Setup
- Never commit secrets: Use environment variables
- Restrict redirect URIs: Only allow your domain
- Minimal scopes: Request only necessary permissions
- Regular rotation: Rotate client secrets periodically
# Use environment variables for sensitive data
export GOOGLE_CLIENT_SECRET="your-secret"
export MICROSOFT_CLIENT_SECRET="your-secret"
# Reference in config files
{
"client_secret": "${GOOGLE_CLIENT_SECRET}"
}
🛡️ Token Management
- Encrypted storage: Tokens encrypted at rest
- Automatic refresh: Handles token expiration
- Scope validation: Verify granted scopes
- Revocation support: Clean disconnection
🔍 Monitoring
- Connection logs: Track OAuth activity
- Error handling: Graceful failure recovery
- Rate limiting: Respect API limits
- Audit trails: Log token usage
Scope Minimization Examples
✅ Good Practice
{
"scopes": [
"profile", // Minimal user info
"email" // Email address only
]
}
❌ Avoid
{
"scopes": [
"admin:everything", // Too broad
"all:permissions" // Excessive access
]
}
🐛 Troubleshooting
Common Issues
❌ "Authenticator not found"
Diagnosis:
# Check if registered correctly
fiber list-authenticators --to-instance your-instance
# Verify app context
ls .fw-data/fw_app_info.json
Solutions:
- Verify authenticator exists and is active
- Check authenticator_id matches exactly
- Ensure correct instance/environment
❌ "Invalid redirect URI"
Diagnosis:
# Check redirect URI format
echo "Should be: https://your-domain.com/auth/callback/{authenticator_type}"
Solutions:
- Add correct callback URL to authenticator settings
- Ensure HTTPS in production
- Match URI exactly in provider console
❌ "Missing required fields"
Required Fields:
{
"name": "Required",
"authenticator_type": "Required",
"client_id": "Required",
"client_secret": "Required"
}
❌ "Insufficient scopes"
Solutions:
- Request additional scopes in authenticator config
- User may need to re-authorize
- Check authenticator-specific scope requirements
Debug Mode
# Enable verbose output
fiber app oauth register-authenticator \
--authenticator-config ./config.json \
--to-instance development \
--verbose
# Enable OAuth debugging
export OAUTH_DEBUG=true
fiber register-authenticator google --debug
# Check OAuth logs
tail -f .fiberwise-core/logs/oauth.log
Testing and Validation
1. Register Test Authenticator
fiber app oauth register-authenticator \
--authenticator-config ./test-google.json \
--to-instance development
2. Verify in Web Interface
- Open Settings → OAuth Authenticators
- Check "Connections" tab shows your authenticator
- Test connection flow
3. CLI Verification
fiber app oauth list-authenticators --to-instance development
📊 Monitoring and Analytics
Connection Success Rates
Track successful OAuth flows and identify bottlenecks
Token Refresh Patterns
Monitor token lifecycle and refresh frequencies
Error Analytics
Identify common failure points and resolution patterns
Provider Performance
Compare different OAuth providers and response times
🎯 Next Steps
🚀 Quick Implementation Checklist
- ☐ Choose development path (CLI or Web)
- ☐ Get OAuth credentials from authenticators
- ☐ Register authenticators using preferred method
- ☐ Test OAuth flow with development instance
- ☐ Implement user connection interface
- ☐ Add error handling for failed flows
- ☐ Monitor usage through platform analytics
- ☐ Deploy to production with proper security
Supported Authenticators
Gmail, Google Drive, Calendar, Contacts
Microsoft
Outlook, OneDrive, Teams, Calendar
GitHub
Repositories, Organizations, Issues
Slack
Channels, Messages, Files, Users
OAuth Data Flow
Complete System Architecture
graph TB subgraph "Developer Setup" CLI[CLI Commands] --> OP[oauth_authenticators table] OP --> |Authenticator Config| FLOW[OAuth Flow Available] end subgraph "User Authentication" USER[User Action] --> SESS[oauth_sessions table] SESS --> |Temporary State| REDIR[OAuth Redirect] REDIR --> |Auth Code| TOKENS[oauth_token_grants table] TOKENS --> |Connection| CONN[user_app_oauth_authentications table] end subgraph "API Usage" APP[App Request] --> LOOKUP[Token Lookup] LOOKUP --> REFRESH{Token Valid?} REFRESH -->|Yes| USE[Use Token] REFRESH -->|No| RENEW[Refresh Token] RENEW --> USE USE --> API[External API Call] end FLOW -.-> USER CONN -.-> APP style CLI fill:#e3f2fd style USER fill:#f3e5f5 style APP fill:#e8f5e8
Token Lifecycle Management
stateDiagram-v2 [*] --> AuthenticatorConfigured: CLI register-authenticator AuthenticatorConfigured --> AuthInitiated: User clicks connect AuthInitiated --> AuthorizationPending: Redirect to authenticator AuthorizationPending --> TokensReceived: User authorizes TokensReceived --> TokensStored: Store in database TokensStored --> Active: Connection active Active --> TokenExpired: Time passes TokenExpired --> RefreshAttempt: Auto refresh RefreshAttempt --> Active: Success RefreshAttempt --> Revoked: Refresh failed Active --> UserRevoked: User disconnects UserRevoked --> Revoked Revoked --> [*]: Connection removed note right of Active: Tokens used for API calls note right of RefreshAttempt: Automatic background process
Authenticator Configuration
Google Setup
Google Cloud Console
Go to Google Cloud Console
Create/select project → Enable APIs → Create OAuth 2.0 credentials
Configure Redirect URI
https://your-domain.com/auth/callback/google
Add Authenticator via CLI
fiber register-authenticator google \
--client-id="123456789-abcdef.apps.googleusercontent.com" \
--client-secret="GOCSPX-your-secret" \
--scopes="profile,email,https://www.googleapis.com/auth/gmail.readonly"
Microsoft Setup
Azure Portal
Go to Azure Portal
Register application → Configure API permissions → Create client secret
Configure Redirect URI
https://your-domain.com/auth/callback/microsoft
Add Authenticator via CLI
fiber register-authenticator microsoft \
--client-id="12345678-1234-1234-1234-123456789abc" \
--client-secret="your-secret" \
--scopes="User.Read,Mail.Read,Calendars.Read"
Common Scopes Reference
Google Scopes
Scope | Description | Use Case |
---|---|---|
profile |
Basic profile information | User identification |
email |
Email address | User contact info |
gmail.readonly |
Read Gmail messages | Email analysis, search |
gmail.modify |
Modify Gmail messages | Email management, labels |
calendar |
Access calendar events | Scheduling, reminders |
Microsoft Scopes
Scope | Description | Use Case |
---|---|---|
User.Read |
Read user profile | User identification |
Mail.Read |
Read user's mail | Email analysis |
Mail.ReadWrite |
Read and write mail | Email management |
Calendars.Read |
Read calendars | Schedule viewing |
Files.Read |
Read user's files | Document access |
Usage in Applications
Frontend Integration
// Import FiberWise SDK
import FiberWise from 'fiberwise';
// Initialize the SDK
const fiber = new FiberWise({
baseUrl: 'https://api.fiberwise.ai/api/v1',
appId: 'your-app-id'
});
// Simple OAuth integration
async function connectGmail() {
try {
// Use SDK to connect to Google OAuth
await fiber.credentials.connectAuthenticator('google', {
returnTo: '/settings'
});
} catch (error) {
console.error('Gmail connection failed:', error);
}
}
// Check connection status using SDK
async function checkGmailConnection() {
try {
return await fiber.credentials.isConnected('google');
} catch (error) {
console.error('Error checking Gmail connection:', error);
return false;
}
}
// List all available authenticators
async function getAvailableAuthenticators() {
try {
return await fiber.credentials.listAuthenticators({
includeDisabled: false
});
} catch (error) {
console.error('Error listing authenticators:', error);
return [];
}
}
// Disconnect from provider
async function disconnectProvider(authenticatorId) {
try {
await fiber.credentials.revokeConnection(authenticatorId);
console.log(`Successfully disconnected from ${authenticatorId}`);
} catch (error) {
console.error(`Failed to disconnect from ${authenticatorId}:`, error);
}
}
Backend Agent Integration
# Python agent using OAuth credentials
from fiberwise import Agent
class EmailProcessorAgent(Agent):
async def process_user_email(self, user_context):
# OAuth credentials automatically injected
gmail_service = await self.get_oauth_service('gmail')
# Fetch recent emails
emails = await gmail_service.get_recent_emails(limit=10)
# Process with LLM
summary = await self.llm.generate(
f"Summarize these emails: {emails}"
)
return {
"email_count": len(emails),
"summary": summary
}
Security Best Practices
🔐 Authenticator Setup
- Never commit secrets: Use environment variables
- Restrict redirect URIs: Only allow your domain
- Minimal scopes: Request only necessary permissions
- Regular rotation: Rotate client secrets periodically
🛡️ Token Management
- Encrypted storage: Tokens encrypted at rest
- Automatic refresh: Handles token expiration
- Scope validation: Verify granted scopes
- Revocation support: Clean disconnection
🔍 Monitoring
- Connection logs: Track OAuth activity
- Error handling: Graceful failure recovery
- Rate limiting: Respect API limits
- Audit trails: Log token usage
Troubleshooting
Common Issues
❌ "Authenticator not found"
Solution:
- Verify authenticator exists:
fiber list-authenticators
- Check authenticator_id matches exactly
- Ensure authenticator is active
❌ "Invalid redirect URI"
Solution:
- Add correct callback URL to authenticator settings
- Format:
https://your-domain.com/auth/callback/{authenticator}
- Ensure HTTPS in production
❌ "Insufficient scopes"
Solution:
- Request additional scopes in authenticator config
- User may need to re-authorize
- Check authenticator-specific scope requirements
Debug Mode
# Enable OAuth debugging
export OAUTH_DEBUG=true
fiber add-provider google --debug
# Check OAuth logs
tail -f .fiberwise-core/logs/oauth.log
CLI Reference
Authenticator Management
# Add OAuth authenticator
fiber register-authenticator {authenticator} \
--client-id="..." \
--client-secret="..." \
--scopes="..."
# List all authenticators
fiber list-authenticators
# Remove authenticator
fiber delete-authenticator {authenticator}
# Update authenticator
fiber update-authenticator {authenticator} --scopes="new,scopes"
Connection Management
# List user connections
curl -H "Authorization: Bearer $API_KEY" \
/api/v1/credentials/connections
# Revoke connection
curl -X DELETE -H "Authorization: Bearer $API_KEY" \
/api/v1/credentials/connections/google
Next Steps
🚀 Implementation Roadmap
- Configure authenticators using
register-authenticator
commands - Test OAuth flow with a simple app
- Implement user UI for connecting accounts
- Add error handling for failed OAuth flows
- Monitor usage through platform analytics