OAuth Troubleshooting
This guide covers common OAuth authentication issues and their solutions across all supported providers (Google, GitHub, Facebook, Microsoft).
Quick Diagnosis
Use this flowchart to quickly identify your issue:
Error during login? → See "Authorization Errors"
Error after callback? → See "Callback Errors"
Token issues? → See "Token Management Errors"
Configuration issues? → See "Configuration Errors"
User experience issues? → See "User Experience Issues"
Authorization Errors
redirect_uri_mismatch
Symptoms:
- Error message: "redirect_uri_mismatch" or "The redirect URI specified in the request does not match"
- User cannot complete OAuth flow
Causes:
- Redirect URI in OpenAPI spec doesn't match provider configuration
- Protocol mismatch (http vs https)
- Trailing slash mismatch
- Domain mismatch
Solutions:
-
Check exact match:
# Your OpenAPI spec redirectUri: http://localhost:3000/auth/callback # Must exactly match provider console # ✅ Correct: http://localhost:3000/auth/callback # ❌ Wrong: http://localhost:3000/auth/callback/ (trailing slash) # ❌ Wrong: https://localhost:3000/auth/callback (protocol) -
Verify in provider console:
- Google: Cloud Console > Credentials > OAuth 2.0 Client IDs
- GitHub: Settings > Developer settings > OAuth Apps
- Facebook: App Dashboard > Facebook Login > Settings
- Microsoft: Azure Portal > App registrations > Authentication
-
Common mistakes:
- Trailing slashes:
http://example.com/auth/callback/vshttp://example.com/auth/callback - Protocol:
http://vshttps:// - Port numbers:
http://localhost:3000vshttp://localhost - Subdomain:
app.example.comvsexample.com
- Trailing slashes:
access_denied
Symptoms:
- Error message: "access_denied" or "User denied access"
- User is redirected back to login page
Causes:
- User clicked "Cancel" or "Deny" on provider consent screen
- User closed the authorization window
Solutions:
- This is expected behavior when users decline authorization
- Display a friendly message: "Authorization was cancelled. Please try again."
- Allow user to retry the OAuth flow
- Consider explaining why permissions are needed
UIGen Behavior: UIGen automatically handles this error and displays a user-friendly message.
invalid_client
Symptoms:
- Error message: "invalid_client" or "Client authentication failed"
- Authorization fails immediately
Causes:
- Incorrect client ID
- Client ID not set in environment variables
- OAuth app deleted or disabled in provider console
Solutions:
-
Verify client ID:
# Check environment variable is set echo $GOOGLE_CLIENT_ID echo $GITHUB_CLIENT_ID echo $FACEBOOK_CLIENT_ID echo $MICROSOFT_CLIENT_ID -
Check for whitespace:
# Remove any extra whitespace export GOOGLE_CLIENT_ID="123456.apps.googleusercontent.com" # Not: export GOOGLE_CLIENT_ID=" 123456.apps.googleusercontent.com " -
Verify in provider console:
- Ensure OAuth app still exists
- Check that app is not disabled
- Confirm you're using the correct client ID (not client secret)
invalid_scope
Symptoms:
- Error message: "invalid_scope" or "The requested scope is invalid"
- Authorization fails with scope error
Causes:
- Requesting scopes not supported by provider
- Typo in scope name
- Requesting scopes that require app review (Facebook)
Solutions:
-
Use default scopes:
# Let UIGen use provider defaults x-uigen-auth: providers: - provider: google clientId: ${GOOGLE_CLIENT_ID} redirectUri: ${REDIRECT_URI} # scopes omitted - uses defaults -
Check scope names:
# Google scopes: - openid - email - profile # GitHub scopes: - read:user - user:email # Facebook scopes: - email - public_profile # Microsoft scopes: - openid - email - profile -
Facebook app review:
- Scopes beyond
emailandpublic_profilerequire app review - Submit app for review or use default scopes
- Scopes beyond
Callback Errors
State Mismatch
Symptoms:
- Error message: "State parameter mismatch" or "Invalid state"
- User redirected back to login after authorization
Causes:
- CSRF protection triggered
- Browser cleared sessionStorage during OAuth flow
- Browser extension interfering with sessionStorage
- User opened callback URL directly
Solutions:
-
Clear browser storage and retry:
// In browser console sessionStorage.clear(); localStorage.clear(); -
Check browser extensions:
- Disable privacy/security extensions temporarily
- Try in incognito/private mode
-
Verify sessionStorage works:
// In browser console sessionStorage.setItem('test', 'value'); console.log(sessionStorage.getItem('test')); // Should print 'value' -
Don't bookmark callback URLs:
- Callback URLs are single-use
- Always start OAuth flow from login page
Token Exchange Failed
Symptoms:
- Error message: "Failed to exchange authorization code for token"
- User authorized but not logged in
Causes:
- Authorization code expired (codes expire in 10 minutes)
- Authorization code already used
- Network timeout during token exchange
- Provider token endpoint unavailable
Solutions:
-
Retry the OAuth flow:
- Authorization codes are single-use
- Start from login page again
-
Check network connectivity:
# Test provider token endpoint curl -I https://oauth2.googleapis.com/token # Google curl -I https://github.com/login/oauth/access_token # GitHub -
Check for duplicate requests:
- Ensure your app doesn't make multiple token exchange requests
- UIGen handles this automatically
-
Increase timeout (if using custom implementation):
- Default timeout is 30 seconds
- Increase if network is slow
bad_verification_code (GitHub)
Symptoms:
- Error message: "bad_verification_code"
- GitHub-specific error after callback
Causes:
- Authorization code expired
- Authorization code already used
- Code was tampered with
Solutions:
- Start OAuth flow again from login page
- Ensure code is not being logged or exposed
- Check that callback handler runs only once
Token Management Errors
Token Expired
Symptoms:
- API requests return 401 Unauthorized
- User logged out unexpectedly
Causes:
- Access token expired (typically 1-2 hours)
- Refresh token expired or revoked
- User revoked app access in provider settings
Solutions:
UIGen automatically handles token refresh:
- Detects 401 responses
- Attempts to refresh access token
- Retries original request
- Redirects to login if refresh fails
Manual check:
// In browser console
console.log(localStorage.getItem('access_token'));
console.log(localStorage.getItem('refresh_token'));
If tokens are missing:
- User needs to log in again
- Check that logout didn't clear tokens unintentionally
Refresh Token Invalid
Symptoms:
- Token refresh fails
- User redirected to login after 401 error
Causes:
- Refresh token expired (typically 90 days for Microsoft, varies by provider)
- User revoked app access
- Refresh token was rotated and old token used
Solutions:
- This is expected behavior - user needs to re-authenticate
- Display message: "Your session has expired. Please log in again."
- Redirect to login page (UIGen does this automatically)
User Revoked Access
Symptoms:
- API requests fail with 401
- Token refresh fails
Causes:
- User revoked app access in provider settings:
- Google: Account Permissions
- GitHub: Authorized OAuth Apps
- Facebook: Apps and Websites
- Microsoft: Account Privacy
Solutions:
- This is expected and user-controlled
- Clear stored tokens and redirect to login
- User can re-authorize if they want
Configuration Errors
Environment Variables Not Set
Symptoms:
- Error message: "Client ID is required"
- OAuth buttons don't appear
- Server fails to start
Causes:
- Environment variables not set
- Typo in environment variable name
- Environment variables not loaded
Solutions:
-
Check environment variables:
# List all OAuth-related variables env | grep -i oauth env | grep -i google env | grep -i github env | grep -i facebook env | grep -i microsoft -
Set environment variables:
export GOOGLE_CLIENT_ID="your-client-id" export GITHUB_CLIENT_ID="your-client-id" export FACEBOOK_CLIENT_ID="your-client-id" export MICROSOFT_CLIENT_ID="your-client-id" export OAUTH_REDIRECT_URI="http://localhost:3000/auth/callback" -
Use .env file:
# Create .env file cat > .env << EOF GOOGLE_CLIENT_ID=your-client-id GITHUB_CLIENT_ID=your-client-id OAUTH_REDIRECT_URI=http://localhost:3000/auth/callback EOF # Load .env file source .env -
Verify in OpenAPI spec:
x-uigen-auth: providers: - provider: google clientId: ${GOOGLE_CLIENT_ID} # Correct syntax # Not: clientId: $GOOGLE_CLIENT_ID # Missing braces
Invalid OpenAPI Configuration
Symptoms:
- Server fails to start
- Validation errors in console
- OAuth buttons don't appear
Causes:
- Invalid provider name
- Missing required fields
- Invalid URL format
- Too many providers (max 10)
Solutions:
-
Check provider name:
# ✅ Correct provider: google provider: github provider: facebook provider: microsoft # ❌ Wrong provider: Google # Case-sensitive provider: gmail # Not a valid provider -
Check required fields:
# All required fields x-uigen-auth: providers: - provider: google # Required clientId: ${CLIENT_ID} # Required redirectUri: ${REDIRECT_URI} # Required scopes: # Optional - openid - email -
Check URL format:
# ✅ Correct redirectUri: http://localhost:3000/auth/callback redirectUri: https://yourdomain.com/auth/callback # ❌ Wrong redirectUri: localhost:3000/auth/callback # Missing protocol redirectUri: http://yourdomain.com/callback # Wrong path -
Check provider limit:
# Maximum 10 providers x-uigen-auth: providers: - provider: google - provider: github # ... up to 10 total
HTTPS Required Error
Symptoms:
- Error message: "HTTPS is required for production"
- Custom OAuth URLs rejected
Causes:
- Using HTTP for custom OAuth endpoints
- Production deployment without HTTPS
Solutions:
-
Development (localhost):
# HTTP is allowed for localhost redirectUri: http://localhost:3000/auth/callback -
Production:
# HTTPS is required redirectUri: https://yourdomain.com/auth/callback -
Custom endpoints:
# Custom endpoints must use HTTPS authorizationUrl: https://custom.provider.com/oauth/authorize tokenUrl: https://custom.provider.com/oauth/token
User Experience Issues
OAuth Buttons Not Appearing
Symptoms:
- Login page shows only credential form
- No OAuth buttons visible
Causes:
- OAuth providers not configured
- All providers disabled
- Environment variables not set
- Configuration validation failed
Solutions:
-
Check configuration:
# Ensure providers are configured x-uigen-auth: providers: - provider: google clientId: ${GOOGLE_CLIENT_ID} redirectUri: ${REDIRECT_URI} enabled: true # Default is true -
Check browser console:
- Open browser developer tools
- Look for configuration errors
- Check network tab for failed requests
-
Verify environment variables:
echo $GOOGLE_CLIENT_ID # Should print your client ID
Email Not Returned
Symptoms:
- User profile missing email address
- Email field is null or undefined
Causes:
- Email scope not requested
- User doesn't have verified email
- User denied email permission
- Provider doesn't return email
Solutions:
-
Request email scope:
scopes: - email # Explicitly request email - profile -
Check user's email status:
- Google: User must have verified email
- GitHub: User must have verified email and made it public or granted access
- Facebook: User must have verified email
- Microsoft: Usually available for work/school accounts
-
Handle missing email gracefully:
// Your application should handle missing email const email = userProfile.email || 'No email provided';
Slow OAuth Flow
Symptoms:
- OAuth flow takes a long time
- Timeout errors
- Poor user experience
Causes:
- Slow network connection
- Provider API slow or unavailable
- Too many API requests
Solutions:
-
Check network:
# Test provider endpoints time curl -I https://accounts.google.com time curl -I https://github.com/login -
Implement loading indicators:
- UIGen shows loading spinners automatically
- Inform users that authentication is in progress
-
Cache user profiles:
- Don't fetch profile on every request
- UIGen caches profiles in localStorage
-
Monitor provider status:
Provider-Specific Issues
Google: "This app isn't verified"
Problem: Google shows warning that app isn't verified.
Solution:
- Development: Click "Advanced" > "Go to [Your App] (unsafe)"
- Production: Submit app for OAuth verification
GitHub: Rate Limiting
Problem: Too many requests to GitHub API.
Solution:
- GitHub limits: 5,000 requests/hour per user
- Cache user profile data
- Consider using GitHub App for higher limits
Facebook: App in Development Mode
Problem: Only test users can log in.
Solution:
- Add users as testers in Roles > Testers
- Or complete app review and switch to Live Mode
Microsoft: Admin Consent Required
Problem: "The grant requires admin permission"
Solution:
- Some permissions require admin consent in organizations
- Contact organization admin
- Or request only permissions that don't require admin consent
Debugging Tips
Enable Verbose Logging
// In browser console
localStorage.setItem('debug', 'oauth:*');
// Reload page to see detailed OAuth logs
Check Browser Storage
// In browser console
console.log('Access Token:', localStorage.getItem('access_token'));
console.log('Refresh Token:', localStorage.getItem('refresh_token'));
console.log('Auth Method:', localStorage.getItem('auth_method'));
console.log('User Profile:', localStorage.getItem('oauth_user_profile'));
console.log('OAuth State:', sessionStorage.getItem('oauth_state_google'));
Test OAuth Flow Manually
-
Get authorization URL:
// In browser console (on login page) // Click OAuth button and copy the redirect URL -
Check callback parameters:
// In browser console (on callback page) const params = new URLSearchParams(window.location.search); console.log('Code:', params.get('code')); console.log('State:', params.get('state')); console.log('Error:', params.get('error')); -
Verify token exchange:
- Check browser network tab
- Look for POST request to token endpoint
- Check response for access_token
Clear All OAuth Data
// In browser console
// Clear all OAuth-related data
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
localStorage.removeItem('auth_method');
localStorage.removeItem('oauth_user_profile');
sessionStorage.clear();
// Reload page
location.reload();
Getting Help
If you're still experiencing issues:
-
Check documentation:
-
Check provider documentation:
-
Check provider status pages:
- Verify provider services are operational
- Check for ongoing incidents
-
Report an issue:
- Include error messages
- Include browser console logs
- Include network tab screenshots
- Include your OpenAPI configuration (remove sensitive data)
Next Steps
- OAuth Configuration - Configure OAuth providers
- OAuth Security Best Practices - Learn about OAuth security
- Google OAuth Setup - Set up Google OAuth
- GitHub OAuth Setup - Set up GitHub OAuth