OAuth 2.0 Implementation Guide
This guide provides comprehensive technical details for implementing OAuth 2.0 with the Fanvue API. If you’re looking for a quick start, see the OAuth 2.0 Tutorial.
OAuth 2.0 Flow Diagram
PKCE (Proof Key for Code Exchange)
PKCE is required for all OAuth 2.0 flows. It’s a security extension that prevents authorization code interception attacks.
How PKCE Works
- Generate a Code Verifier: Create a cryptographically random string (43-128 characters)
- Create a Code Challenge: Hash the verifier using SHA-256 and encode it as Base64URL
- Send Challenge with Authorization: Include
code_challengein the authorization request - Store Verifier Securely: Keep the
code_verifierin your application (see storage options below) - Send Verifier with Token Exchange: Include
code_verifierwhen exchanging the authorization code - Server Verification: Fanvue verifies that
SHA256(code_verifier)matches the originalcode_challenge
This ensures that even if an attacker intercepts the authorization code, they cannot exchange it for tokens without the original code_verifier.
Storing the Code Verifier
You must securely store the code_verifier between the authorization request and token exchange:
Recommended Options:
- Server-side session storage (preferred): Store in Redis, database, or in-memory session
- Secure HTTP-only cookies: Use
Secure,HttpOnly, andSameSite=Laxflags - Encrypted client storage: Only if server-side storage isn’t possible
⚠️ Never store the verifier in:
- Local storage or session storage (vulnerable to XSS)
- URL parameters
- Client-side JavaScript variables that persist across page loads
Code Examples
JavaScript/Node.js
Python
Other Languages
Authorization URL Format
You should always include these default scopes:
openid- Required for OpenID Connect; enables ID token generation and access to user identityoffline_access- Provides refresh tokens so your app can obtain new access tokens without re-authenticationoffline- Enables long-term access for background operations
Required Parameters:
client_id- Your OAuth application’s client IDredirect_uri- Where users are redirected after authorization (must match your app configuration)response_type=code- Indicates authorization code flowscope- Space-separated list of permissions (URL encoded with+)state- Random string to prevent CSRF attacks (verify this matches on callback)code_challenge- [PKCE Required] The Base64URL-encoded SHA-256 hash of yourcode_verifiercode_challenge_method=S256- [PKCE Required] Indicates SHA-256 hashing method
Token Exchange
After receiving the authorization code, exchange it for access and refresh tokens.
Required Parameters:
grant_type=authorization_code- Indicates you’re exchanging an authorization codeclient_id- Your OAuth application’s client IDclient_secret- Your OAuth application’s client secretcode- The authorization code received from the callbackredirect_uri- Must match the redirect URI used in the authorization requestcode_verifier- [PKCE Required] The originalcode_verifieryou generated (NOT the challenge)
⚠️ Important: Send the code_verifier, not the code_challenge. The server will hash the verifier and compare it to the challenge you sent earlier.
Response:
Handling the OAuth Callback
After the user authorizes your application, Fanvue redirects them back to your specified redirect_uri with the authorization code and state parameter.
Callback URL Format
Implementation Examples
Express.js
Next.js (App Router)
Flask
FastAPI
Key Implementation Points
- State Validation: Always validate the
stateparameter to prevent CSRF attacks - Retrieve Code Verifier: Get the stored
code_verifierfrom session/cookies - Error Handling: Handle missing parameters and failed token exchanges gracefully
- Clean Up: Remove temporary session data after successful exchange
- Secure Storage: Store tokens securely (encrypted database preferred over sessions)
Token Refresh Flow
Access tokens expire after a short period (typically 1 hour). Use refresh tokens to obtain new access tokens without requiring users to re-authenticate.
Refresh Token Request
Response:
Automatic Token Refresh Implementation
JavaScript/Node.js
Python
Token Refresh Best Practices
- Proactive Refresh: Refresh tokens before they expire (5-10 minutes buffer)
- Handle Concurrent Requests: Use locks/promises to prevent multiple simultaneous refresh attempts
- Retry Logic: If a request fails with 401, try refreshing the token once and retry
- Secure Storage: Store refresh tokens securely and encrypted
- Update Both Tokens: The refresh response may include a new refresh token - always update both
- Error Handling: If refresh fails, redirect user to re-authenticate
Best Practices
Security
- PKCE is mandatory - Always implement PKCE for all OAuth flows (see PKCE section above)
- Code Verifier Requirements:
- Minimum 43 characters, maximum 128 characters
- Use cryptographically secure random generation
- Store securely server-side (session/Redis preferred) or in HTTP-only cookies
- Never expose in URLs, local storage, or client-side JavaScript
- Always use HTTPS in production
- Store tokens securely (encrypted at rest)
- Implement proper token refresh logic
- Use the
stateparameter to prevent CSRF attacks (minimum 32 random characters) - Validate redirect URIs match exactly what’s configured in your app
- Keep your Client Secret secure and never expose it in client-side code
User Experience
- Clearly explain what permissions your app needs
- Handle authorization errors gracefully
- Provide a way for users to disconnect your app
- Respect rate limits and user privacy
Token Management
- Access tokens are short-lived (typically 1 hour)
- Use refresh tokens to get new access tokens
- Handle token expiration gracefully
- Revoke tokens when users disconnect
- Implement automatic token refresh before expiration
Troubleshooting
Common Errors
This section provides code examples for handling common OAuth errors.
Invalid Client ID
Error Response:
Solutions:
- Verify your Client ID is correct
- Ensure the app is active in your developer dashboard
Redirect URI Mismatch
Error Response:
Solutions:
- Check that the redirect URI matches exactly what’s configured
- Ensure the URI is properly URL-encoded
- Verify protocol (http vs https) matches exactly
Invalid Scope
Error Response:
Solutions:
- Verify the requested scopes are available and properly formatted
- Check that your app has been granted the necessary permissions
- Ensure scopes are space-separated and URL-encoded with
+
Token Expired
Error Response:
Solutions:
- Implement automatic token refresh (see Token Refresh Flow section)
- Handle 401 responses by refreshing tokens
PKCE Validation Failed
Error Response:
Solutions:
- Ensure you’re sending the original
code_verifier, not thecode_challenge - Verify the code verifier is stored and retrieved correctly
- Check that the same verifier used to generate the challenge is sent in token exchange
Error Handling Implementation
JavaScript/Node.js
Python
Best Practices for Error Handling
- Distinguish Error Types: Separate OAuth errors, network errors, and application errors
- Provide Context: Log enough information to debug issues without exposing secrets
- Retry Strategically: Retry on server errors (5xx) and rate limits (429), not client errors (4xx)
- Exponential Backoff: Wait longer between each retry attempt
- User-Friendly Messages: Show helpful error messages to users, not raw error codes
- Monitor Errors: Track error rates to identify systemic issues
Support
For additional help with OAuth 2.0 integration:
- Quick Start: See the OAuth 2.0 Tutorial for a getting started guide
- Implementation: Follow our Quickstart Guide for a complete Next.js example
- API Reference: Check our API documentation
- App Management: Visit the developer portal
- Template: Review the starter template on GitHub