Authentication Troubleshooting
Debug and resolve common authentication issues with Agent Auth, including OAuth failures, token problems, and provider-specific errors.
This guide helps you diagnose and resolve common authentication issues with Agent Auth. Use the troubleshooting steps below to quickly identify and fix problems with connected accounts, OAuth flows, and token management.
Quick diagnostics
Section titled “Quick diagnostics”Start with these quick checks to identify the issue:
Check connected account status
Section titled “Check connected account status”# Get connected account statusaccount = actions.get_connected_account( identifier="user_123", connection_name="gmail")
print(f"Status: {account.status}")print(f"Provider: {account.connection_name}")print(f"Created: {account.created_at}")print(f"Updated: {account.updated_at}")
# Status values:# - PENDING: User hasn't completed authentication# - ACTIVE: Connection is active and working# - EXPIRED: Tokens expired, refresh may be needed# - REVOKED: User revoked access# - ERROR: Authentication error occurred// Get connected account statusconst account = await scalekit.actions.getConnectedAccount({ identifier: 'user_123', connectionName: 'gmail'});
console.log(`Status: ${account.status}`);console.log(`Provider: ${account.connectionName}`);console.log(`Created: ${account.createdAt}`);console.log(`Updated: ${account.updatedAt}`);
// Status values:// - PENDING: User hasn't completed authentication// - ACTIVE: Connection is active and working// - EXPIRED: Tokens expired, refresh may be needed// - REVOKED: User revoked access// - ERROR: Authentication error occurred// Get connected account statusaccount, err := scalekitClient.Actions.GetConnectedAccount( context.Background(), "user_123", "gmail",)if err != nil { log.Printf("Error getting account: %v", err) return}
fmt.Printf("Status: %s\n", account.Status)fmt.Printf("Provider: %s\n", account.ConnectionName)fmt.Printf("Created: %s\n", account.CreatedAt)fmt.Printf("Updated: %s\n", account.UpdatedAt)// Get connected account statusConnectedAccount account = scalekitClient.actions().getConnectedAccount( "user_123", "gmail");
System.out.println("Status: " + account.getStatus());System.out.println("Provider: " + account.getConnectionName());System.out.println("Created: " + account.getCreatedAt());System.out.println("Updated: " + account.getUpdatedAt());Test tool execution
Section titled “Test tool execution”Try executing a simple tool to verify the connection:
# Test with a simple read operationtry: result = actions.execute_tool( identifier="user_123", tool_name='gmail_get_profile', # Simple read-only operation tool_input={} ) print("✓ Connection working:", result)except Exception as e: print("✗ Connection failed:", str(e)) # Error message provides clues about the issueCommon authentication errors
Section titled “Common authentication errors”PENDING status - User hasn’t authenticated
Section titled “PENDING status - User hasn’t authenticated”Symptom: Connected account status shows PENDING
Cause: User created the connected account but hasn’t completed OAuth flow
Solution:
- Generate a new authorization link
- Send it to the user via email, notification, or in-app message
- User clicks link and completes authentication
- Status changes to
ACTIVE
# Generate authorization link for pending accountif account.status == "PENDING": link_response = actions.get_authorization_link( connection_name="gmail", identifier="user_123" )
print(f"Send this link to user: {link_response.link}")
# In production: # - Send email with the link # - Show in-app notification # - Display in user's settings page// Generate authorization link for pending accountif (account.status === 'PENDING') { const linkResponse = await scalekit.actions.getAuthorizationLink({ connectionName: 'gmail', identifier: 'user_123' });
console.log(`Send this link to user: ${linkResponse.link}`);
// In production: // - Send email with the link // - Show in-app notification // - Display in user's settings page}// Generate authorization link for pending accountif account.Status == "PENDING" { linkResponse, err := scalekitClient.Actions.GetAuthorizationLink( context.Background(), "gmail", "user_123", ) if err != nil { log.Fatal(err) }
fmt.Printf("Send this link to user: %s\n", linkResponse.Link)}// Generate authorization link for pending accountif ("PENDING".equals(account.getStatus())) { AuthorizationLink linkResponse = scalekitClient.actions().getAuthorizationLink( "gmail", "user_123" );
System.out.println("Send this link to user: " + linkResponse.getLink());}EXPIRED status - Tokens need refresh
Section titled “EXPIRED status - Tokens need refresh”Symptom: Connected account status shows EXPIRED
Causes:
- Access token expired and automatic refresh failed
- Refresh token became invalid
- Provider temporarily unavailable during refresh
Solutions:
Option 1: Try manual refresh
# Attempt manual token refreshtry: account = actions.refresh_connected_account( identifier="user_123", connection_name="gmail" ) if account.status == "ACTIVE": print("✓ Refresh successful") else: print("⚠ Refresh failed, user re-authentication needed")except Exception as e: print(f"✗ Refresh error: {e}") # Proceed to Option 2Option 2: Request user re-authentication
# If refresh fails, generate new authorization linklink_response = actions.get_authorization_link( connection_name="gmail", identifier="user_123")
# Notify user to re-authenticateprint(f"Please re-authorize: {link_response.link}")REVOKED status - User revoked access
Section titled “REVOKED status - User revoked access”Symptom: Connected account status shows REVOKED
Cause: User revoked your application’s access through the provider’s settings (e.g., Google Account Settings, Microsoft Account Permissions)
Solution: User must re-authenticate to restore access
# For revoked accounts, only re-authentication worksif account.status == "REVOKED": link_response = actions.get_authorization_link( connection_name="gmail", identifier="user_123" )
# Explain to user why re-authentication is needed message = """ Your Gmail connection was disconnected. This may have happened if you: - Revoked access in your Google Account settings - Changed your Google password - Enabled 2FA on your Google account
Please reconnect: {link} """.format(link=link_response.link)
print(message)OAuth flow issues
Section titled “OAuth flow issues”Callback errors
Section titled “Callback errors”Symptom: OAuth redirect fails or returns error
Common errors and solutions:
| Error Code | Meaning | Solution |
|---|---|---|
access_denied | User cancelled OAuth flow | Normal behavior, offer retry option |
invalid_request | Malformed OAuth request | Check OAuth parameters and scopes |
unauthorized_client | OAuth client not authorized | Verify OAuth credentials in Scalekit dashboard |
invalid_scope | Requested scope not valid | Review and correct requested scopes |
server_error | Provider error | Retry after a few minutes, check provider status |
Debugging callback issues:
# In your OAuth callback handlerdef handle_oauth_callback(request): error = request.args.get('error') error_description = request.args.get('error_description') code = request.args.get('code') state = request.args.get('state')
if error: # Log the error for debugging print(f"OAuth error: {error}") print(f"Description: {error_description}")
# Handle specific errors if error == 'access_denied': return "You cancelled the authorization. Please try again." elif error == 'invalid_scope': return "Invalid permissions requested. Please contact support." else: return f"Authorization failed: {error_description}"
if not code: return "Missing authorization code"
# Continue with normal flow # Scalekit handles the code exchange automatically return "Authorization successful!"Redirect URI mismatch
Section titled “Redirect URI mismatch”Symptom: Error message about redirect URI mismatch
Cause: OAuth provider redirect URI doesn’t match configured URI in connection
Solution:
- Check the redirect URI in Scalekit dashboard
- Navigate to Connections > Select connection > View Redirect URI
- Copy the exact Scalekit redirect URI
- Add it to your OAuth application in provider’s console (Google, Microsoft, etc.)
- Ensure there are no trailing slashes or protocol mismatches (http vs https)
State parameter validation failure
Section titled “State parameter validation failure”Symptom: “Invalid state parameter” error
Cause: State parameter doesn’t match or is missing (CSRF protection)
Solution:
This is handled automatically by Scalekit, but if you encounter this:
- Ensure cookies are enabled in the browser
- Check for clock skew between systems
- Verify user isn’t switching browsers/devices mid-flow
- Try clearing browser cookies and restarting flow
Provider-specific issues
Section titled “Provider-specific issues”Google Workspace
Section titled “Google Workspace”Issue: “Access blocked: Authorization Error”
Causes:
- App not verified by Google
- Using restricted scopes
- Domain admin restrictions
Solutions:
- Complete Google’s app verification process
- Use less restrictive scopes during development
- Contact domain admin to whitelist your app
Issue: “This app isn’t verified”
Solution:
- Click “Advanced” → “Go to [Your App] (unsafe)” for testing
- Submit app for Google verification for production
- Use Scalekit’s shared credentials for quick testing
Microsoft 365
Section titled “Microsoft 365”Issue: “AADSTS65001: User or administrator has not consented”
Solution:
- Ensure required permissions are configured in Azure AD
- Admin consent may be required for certain scopes
- Check tenant-specific restrictions
Issue: “AADSTS50020: User account from identity provider does not exist”
Solution:
- User must have a valid Microsoft 365 account
- Check if user’s tenant allows external app access
- Verify user’s email domain matches tenant
Issue: “OAuth access denied”
Solution:
- User must have permission to install apps in their Slack workspace
- Check workspace app approval settings
- Ensure required scopes are not restricted by workspace admin
Issue: “Workspace installation restricted”
Solution:
- Contact Slack workspace admin
- Request app approval if workspace requires it
- Use a different workspace for testing
Tool execution failures
Section titled “Tool execution failures”Authentication errors during execution
Section titled “Authentication errors during execution”Symptom: Tool execution fails with authentication error despite ACTIVE status
Debugging steps:
# Step 1: Verify account statusaccount = actions.get_connected_account( identifier="user_123", connection_name="gmail")print(f"Status: {account.status}")
# Step 2: Try to refresh tokenstry: account = actions.refresh_connected_account( identifier="user_123", connection_name="gmail" ) print("✓ Token refresh successful")except Exception as e: print(f"✗ Token refresh failed: {e}")
# Step 3: Check granted scopesprint(f"Granted scopes: {account.scopes}")# Verify the required scope for your tool is included
# Step 4: Try a simple read-only tooltry: result = actions.execute_tool( identifier="user_123", tool_name='gmail_get_profile', tool_input={} ) print("✓ Read operation successful")except Exception as e: print(f"✗ Read operation failed: {e}")Insufficient permissions
Section titled “Insufficient permissions”Symptom: “Insufficient permissions” or “Forbidden” error
Cause: Required scope not granted during authentication
Solution:
- Check currently granted scopes
- Determine required scopes for the tool
- Request additional scopes by having user re-authenticate
- Update connection scopes if needed
# Check if specific scope is grantedrequired_scope = "https://www.googleapis.com/auth/gmail.send"
account = actions.get_connected_account( identifier="user_123", connection_name="gmail")
if required_scope not in account.scopes: print(f"⚠ Missing required scope: {required_scope}")
# Generate new authorization link with required scopes link_response = actions.get_authorization_link( connection_name="gmail", identifier="user_123" )
print(f"User must re-authorize with additional permissions: {link_response.link}")Connection configuration issues
Section titled “Connection configuration issues”Invalid OAuth credentials
Section titled “Invalid OAuth credentials”Symptom: “Invalid client” or “Client authentication failed”
Cause: OAuth client ID or client secret incorrect or revoked
Solution:
- Navigate to Scalekit dashboard → Connections
- Select the affected connection
- Verify OAuth credentials match provider’s console
- If using BYOC (Bring Your Own Credentials), double-check:
- Client ID is correct
- Client Secret hasn’t been regenerated
- OAuth application is active in provider’s console
- Update credentials if needed
- Test connection with a new connected account
Missing or incorrect scopes
Section titled “Missing or incorrect scopes”Symptom: Authorization succeeds but tool execution fails
Cause: Connection configured with insufficient scopes
Solution:
# Check connection configuration in dashboard# Ensure these scopes are configured:
# For Gmail:# - https://www.googleapis.com/auth/gmail.readonly (read emails)# - https://www.googleapis.com/auth/gmail.send (send emails)# - https://www.googleapis.com/auth/gmail.modify (modify emails)
# For Google Calendar:# - https://www.googleapis.com/auth/calendar.readonly (read calendar)# - https://www.googleapis.com/auth/calendar.events (manage events)
# After updating scopes in connection, existing users must re-authenticateRate limiting and quota issues
Section titled “Rate limiting and quota issues”Provider rate limits exceeded
Section titled “Provider rate limits exceeded”Symptom: “Rate limit exceeded” or “Quota exceeded” errors
Causes:
- Too many requests in short time period
- Shared quota limits (when using Scalekit’s shared credentials)
- Provider-specific rate limits
Solutions:
Immediate:
- Implement exponential backoff and retry logic
- Reduce request frequency
- Batch operations where possible
Long-term:
- Use Bring Your Own Credentials for dedicated quotas
- Implement request queuing
- Cache frequently accessed data
import timefrom typing import Any, Dict
def execute_tool_with_retry( identifier: str, tool_name: str, tool_input: Dict[str, Any], max_retries: int = 3): """Execute tool with exponential backoff retry logic""" for attempt in range(max_retries): try: result = actions.execute_tool( identifier=identifier, tool_name=tool_name, tool_input=tool_input ) return result except Exception as e: if "rate limit" in str(e).lower() and attempt < max_retries - 1: # Exponential backoff: 1s, 2s, 4s wait_time = 2 ** attempt print(f"Rate limited, retrying in {wait_time}s...") time.sleep(wait_time) else: raise
# Usageresult = execute_tool_with_retry( identifier="user_123", tool_name="gmail_send_email", tool_input={"to": "user@example.com", "subject": "Test", "body": "Hello"})Network and connectivity issues
Section titled “Network and connectivity issues”Timeout errors
Section titled “Timeout errors”Symptom: Requests timeout or take too long
Causes:
- Network connectivity issues
- Provider API slow response
- Large data transfers
Solutions:
- Increase timeout settings in your application
- Implement async processing for slow operations
- Check provider status page for known issues
- Retry with exponential backoff
SSL/TLS errors
Section titled “SSL/TLS errors”Symptom: SSL certificate verification failures
Causes:
- Outdated SSL certificates
- Corporate proxy/firewall issues
- System clock skew
Solutions:
- Update system CA certificates
- Configure proxy settings if behind corporate firewall
- Verify system clock is synchronized
- Check firewall allows connections to Scalekit and provider domains
Debugging tools and techniques
Section titled “Debugging tools and techniques”Enable detailed logging
Section titled “Enable detailed logging”import logging
# Enable debug logging for Scalekit SDKlogging.basicConfig(level=logging.DEBUG)logger = logging.getLogger('scalekit')logger.setLevel(logging.DEBUG)
# Now all API requests/responses will be loggedresult = actions.execute_tool(...)// Enable debug mode in SDK initializationconst scalekit = new ScalekitClient({ clientId: process.env.SCALEKIT_CLIENT_ID, clientSecret: process.env.SCALEKIT_CLIENT_SECRET, envUrl: process.env.SCALEKIT_ENV_URL, debug: true // Enable detailed logging});// Enable debug loggingscalekitClient := scalekit.NewScalekitClient( scalekit.WithClientID(os.Getenv("SCALEKIT_CLIENT_ID")), scalekit.WithClientSecret(os.Getenv("SCALEKIT_CLIENT_SECRET")), scalekit.WithEnvURL(os.Getenv("SCALEKIT_ENV_URL")), scalekit.WithDebug(true), // Enable debug mode)// Enable debug loggingScalekitClient scalekitClient = new ScalekitClient.Builder() .clientId(System.getenv("SCALEKIT_CLIENT_ID")) .clientSecret(System.getenv("SCALEKIT_CLIENT_SECRET")) .envUrl(System.getenv("SCALEKIT_ENV_URL")) .debug(true) // Enable debug mode .build();Check Scalekit dashboard
Section titled “Check Scalekit dashboard”The Scalekit dashboard provides detailed information:
- Navigate to Agent Auth → Connected Accounts
- Find the affected connected account
- View:
- Current status and last updated time
- Authentication events and errors
- Token refresh history
- Tool execution logs
- Error messages and stack traces
Test with curl
Section titled “Test with curl”Test authentication directly with curl to isolate issues:
# Get connected account statuscurl -X GET "https://api.scalekit.com/v1/connect/accounts/{account_id}" \ -H "Authorization: Bearer YOUR_API_TOKEN"
# Refresh tokenscurl -X POST "https://api.scalekit.com/v1/connect/accounts/{account_id}/refresh" \ -H "Authorization: Bearer YOUR_API_TOKEN"
# Execute toolcurl -X POST "https://api.scalekit.com/v1/connect/tools/execute" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "connected_account_id": "account_123", "tool_name": "gmail_get_profile", "tool_input": {} }'Getting help
Section titled “Getting help”Information to provide
Section titled “Information to provide”When contacting support, include:
- Connected Account ID: Found in dashboard or API response
- Connection Name: Which provider (gmail, slack, etc.)
- Error Messages: Complete error text and stack traces
- Timestamp: When the error occurred
- Steps to Reproduce: What actions led to the error
- Expected Behavior: What should have happened
- Environment: Development, staging, or production
Support channels
Section titled “Support channels”- Documentation: Check related guides in docs
- Dashboard Logs: Review logs in Scalekit dashboard
- Support Portal: Submit ticket with details above
- Developer Community: Ask questions in community forums
- Email Support: support@scalekit.com for critical issues
Next steps
Section titled “Next steps”- Token Management - Understanding token lifecycle
- Scopes and Permissions - Managing OAuth scopes
- Multi-Provider Authentication - Managing multiple connections