OpenRouter OAuth Integration
Overview
OpenRouter is now fully integrated as a provider in Vibe Browser with OAuth authentication support. Unlike OpenAI (which doesn't offer public OAuth), OpenRouter provides a simple OAuth PKCE flow that actually works.
Why OpenRouter OAuth Works
| Feature | OpenAI | OpenRouter |
|---|---|---|
| Public OAuth | ❌ No | Yes |
| Client ID Required | N/A | ❌ No |
| Pre-registration | N/A | ❌ No |
| Works Now | ❌ |
How It Works
User Flow
- User selects an OpenRouter model (e.g.,
openrouter:anthropic/claude-3.5-sonnet) - If no API key is set, a "Quick Connect" button appears
- User clicks "Connect"
- Redirected to OpenRouter login page
- User authorizes Vibe Browser
- Returns with permanent API key
- API key stored securely in Chrome storage
Technical Flow
┌─────────────┐
│ User │
└──────┬──────┘
│ 1. Select openrouter:* model
▼
┌─────────────────┐
│ Settings Page │ (OAuth button appears)
└──────┬──────────┘
│ 2. Click "Connect"
▼
┌─────────────────┐
│ OAuth Service │ Generate PKCE challenge
└──────┬──────────┘
│ 3. Redirect to OpenRouter
▼
┌──────────────────────────────────────┐
│ https://openrouter.ai/auth? │
│ callback_url=chrome-extension:// │
│ code_challenge=xxx │
│ code_challenge_method=S256 │
│ state=random-uuid │
└──────┬───────────────────────────────┘
│ 4. User logs in & approves
▼
┌─────────────────┐
│ Callback │ Returns with code
└──────┬──────────┘
│ 5. Exchange code for API key
▼
┌─────────────────────────────────────┐
│ POST /api/v1/auth/keys │
│ { code, code_verifier } │
└──────┬──────────────────────────────┘
│ 6. Returns: { key: "sk-or-v1-xxx" }
▼
┌─────────────────┐
│ Token Manager │ Store API key
└─────────────────┘
Implementation Details
OAuth Configuration
// apps/chat4/src/services/oauth.ts
openrouter: {
clientId: 'NOT_REQUIRED',
authUrl: 'https://openrouter.ai/auth',
tokenUrl: 'https://openrouter.ai/api/v1/auth/keys',
scopes: [],
usesPKCE: true
}
Authorization Request
GET https://openrouter.ai/auth?
callback_url=https://<EXTENSION_ID>.chromiumapp.org/
&code_challenge=<BASE64_SHA256_HASH>
&code_challenge_method=S256
&state=<RANDOM_UUID>
Key Differences from Standard OAuth:
- Uses
callback_urlinstead ofredirect_uri - No
client_idparameter - No
response_typeparameter - No
scopeparameter
Token Exchange
POST https://openrouter.ai/api/v1/auth/keys
Content-Type: application/json
{
"code": "auth_code_from_callback",
"code_verifier": "random_string_from_pkce"
}
Response:
{
"key": "sk-or-v1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Key Differences:
- Returns actual API key (not access_token)
- No refresh_token (keys don't expire)
- No expires_in (keys are permanent)
- Uses JSON POST (not form-urlencoded)
Provider Configuration
Already configured in:
apps/chat4/src/constants/providers.ts- Provider infolib/utils/initChatModel.js- Uses ChatOpenAI with custom baseURLapps/chat4/src/constants/models.ts- Popular OpenRouter models
Base URL:
https://openrouter.ai/api/v1
OpenRouter is OpenAI-compatible, so it uses the same ChatOpenAI class from LangChain.
Available Models
OpenRouter provides access to models from multiple providers:
// Anthropic via OpenRouter
'openrouter:anthropic/claude-3.5-sonnet'
'openrouter:anthropic/claude-3-opus'
'openrouter:anthropic/claude-3-haiku'
// Google via OpenRouter
'openrouter:google/gemini-2.5-flash-preview-09-2025'
'openrouter:google/gemini-2.0-flash-exp:free'
// Meta via OpenRouter
'openrouter:meta-llama/llama-3.3-70b-instruct'
'openrouter:meta-llama/llama-3.1-405b-instruct'
// DeepSeek via OpenRouter
'openrouter:deepseek/deepseek-chat'
'openrouter:deepseek/deepseek-r1'
// xAI via OpenRouter
'openrouter:x-ai/grok-4-fast'
'openrouter:x-ai/grok-2'
// And many more...
User Benefits
With OAuth:
- One-click authentication
- No copy/paste of API keys
- Automatic account linking
- User controls spending in OpenRouter dashboard
- Can revoke access anytime
Without OAuth (Manual API Key):
- Still works fine
- User gets key from: https://openrouter.ai/keys
- Paste into settings
- Both methods supported
Testing
1. Build Extension
npm run build:extension
2. Test OAuth Flow
- Load extension in Chrome
- Go to settings
- Select model:
openrouter:anthropic/claude-3.5-sonnet - "Quick Connect" button should appear
- Click "Connect"
- Should redirect to OpenRouter login
- Log in with OpenRouter account
- Approve access
- Should return to Vibe with API key set
3. Verify API Key
Check in Chrome DevTools:
chrome.storage.local.get('vibe_oauth_token_openrouter', (result) => {
console.log(result);
});
Should show:
{
"vibe_oauth_token_openrouter": "{\"access_token\":\"sk-or-v1-xxx\",\"provider\":\"openrouter\",\"created_at\":1234567890}"
}
4. Test API Call
Try running a query with the OpenRouter model. Should work without manual API key.
Troubleshooting
OAuth button doesn't appear
- Ensure you selected an
openrouter:*model - Ensure no API key is already set
- Check browser console for errors
Redirect fails
- Verify extension ID matches callback URL
- Check Chrome Identity API is available
- Look for errors in service worker console
Token exchange fails
- Check network tab for API response
- Verify PKCE challenge/verifier match
- Ensure code hasn't expired (use quickly)
API calls fail with OAuth key
- Verify key starts with
sk-or-v1- - Check OpenRouter dashboard for usage/limits
- Try manual API key to isolate OAuth vs API issue
Security
PKCE Protection
- Code verifier: 32 random bytes, base64url encoded
- Code challenge: SHA-256 hash of verifier
- Prevents authorization code interception attacks
Storage
- API key stored in
chrome.storage.local - Chrome provides encryption at rest
- Only accessible by extension
No Client Secret
- OpenRouter doesn't use client secrets (public client)
- PKCE replaces client secret for security
- Safe for browser extensions
Comparison with Manual API Keys
| Aspect | OAuth | Manual API Key |
|---|---|---|
| Setup | One click | Copy/paste |
| Security | PKCE protected | User responsibility |
| Revocation | Via OpenRouter dashboard | Delete key |
| User Experience | Best | Good |
| Reliability | Same API key format | Same API key format |
| Expiration | Never | Never |
Future Enhancements
- Show account info (email, credits) after OAuth
- Allow switching between multiple OpenRouter accounts
- Show usage statistics from OpenRouter API
- Add OAuth for other providers if they support it
- Implement token revocation on disconnect