Token Management
Learn how Scalekit manages access tokens, refresh tokens, and token lifecycle for Agent Auth connections.
Token management is a critical aspect of Agent Auth that ensures your users’ connections remain active and secure. Scalekit automatically handles the complete token lifecycle, including storage, refresh, and expiration, so you can focus on building your application.
Understanding tokens
Section titled “Understanding tokens”When users authenticate with third-party providers through Agent Auth, Scalekit securely manages several types of tokens:
Access tokens
Section titled “Access tokens”Access tokens are short-lived credentials used to make authenticated API requests to third-party providers on behalf of users.
Characteristics:
- Lifetime: Typically 1-2 hours (varies by provider)
- Purpose: Authorize API requests to provider endpoints
- Security: Encrypted at rest and in transit
- Usage: Automatically included in tool execution requests
Refresh tokens
Section titled “Refresh tokens”Refresh tokens are long-lived credentials used to obtain new access tokens when they expire.
Characteristics:
- Lifetime: Typically 30-90 days or indefinite (varies by provider)
- Purpose: Obtain new access tokens without user re-authentication
- Security: Encrypted and stored securely by Scalekit
- Usage: Automatically used when access tokens expire
Token metadata
Section titled “Token metadata”Additional information stored with tokens:
- Expiration time: When the access token expires
- Granted scopes: Permissions the user granted
- Provider account ID: User’s identifier with the provider
- Token type: OAuth 2.0, API key, Bearer token, etc.
Automatic token refresh
Section titled “Automatic token refresh”Scalekit automatically handles token refresh to ensure uninterrupted service for your users.
How automatic refresh works
Section titled “How automatic refresh works”- Token expiration detection - Scalekit monitors token expiration times
- Proactive refresh - Tokens are refreshed 5 minutes before expiration
- Transparent refresh - Refresh happens without interrupting tool execution
- Status update - Connected account status updated upon successful refresh
- Error handling - Failed refreshes trigger appropriate error states
Refresh timing
Section titled “Refresh timing”Token refresh during tool execution
Section titled “Token refresh during tool execution”When you execute a tool, Scalekit automatically handles token refresh if needed:
# You don't need to check token expiration manuallyresult = actions.execute_tool( identifier="user_123", tool_name='gmail_send_email', tool_input={ 'to': 'recipient@example.com', 'subject': 'Hello', 'body': 'This is a test email' })
# Scalekit automatically:# 1. Checks if access token is valid# 2. Refreshes token if expired or expiring soon# 3. Executes the tool with valid token# 4. Returns result or errorManual token refresh
Section titled “Manual token refresh”While Scalekit handles automatic refresh, you can manually refresh tokens when needed:
Check token status
Section titled “Check token status”Verify the current token status before manual operations:
# Get connected account detailsaccount = actions.get_connected_account( identifier="user_123", connection_name="gmail")
# Check account statusif account.status == "ACTIVE": print("✓ Tokens are valid")elif account.status == "EXPIRED": print("⚠ Tokens expired, refresh needed")elif account.status == "REVOKED": print("✗ User revoked access, re-authentication needed")// Get connected account detailsconst account = await scalekit.actions.getConnectedAccount({ identifier: 'user_123', connectionName: 'gmail'});
// Check account statusif (account.status === 'ACTIVE') { console.log('✓ Tokens are valid');} else if (account.status === 'EXPIRED') { console.log('⚠ Tokens expired, refresh needed');} else if (account.status === 'REVOKED') { console.log('✗ User revoked access, re-authentication needed');}// Get connected account detailsaccount, err := scalekitClient.Actions.GetConnectedAccount( context.Background(), "user_123", "gmail",)if err != nil { log.Fatal(err)}
// Check account statusswitch account.Status {case "ACTIVE": fmt.Println("✓ Tokens are valid")case "EXPIRED": fmt.Println("⚠ Tokens expired, refresh needed")case "REVOKED": fmt.Println("✗ User revoked access, re-authentication needed")}// Get connected account detailsConnectedAccount account = scalekitClient.actions().getConnectedAccount( "user_123", "gmail");
// Check account statusswitch (account.getStatus()) { case "ACTIVE": System.out.println("✓ Tokens are valid"); break; case "EXPIRED": System.out.println("⚠ Tokens expired, refresh needed"); break; case "REVOKED": System.out.println("✗ User revoked access, re-authentication needed"); break;}Force token refresh
Section titled “Force token refresh”Manually trigger a token refresh when needed:
# Manually refresh tokenstry: account = actions.refresh_connected_account( identifier="user_123", connection_name="gmail" ) print(f"✓ Tokens refreshed successfully") print(f" Status: {account.status}")except Exception as e: print(f"✗ Token refresh failed: {e}") # Handle refresh failure - may need user re-authentication// Manually refresh tokenstry { const account = await scalekit.actions.refreshConnectedAccount({ identifier: 'user_123', connectionName: 'gmail' }); console.log('✓ Tokens refreshed successfully'); console.log(` Status: ${account.status}`);} catch (error) { console.error(`✗ Token refresh failed: ${error.message}`); // Handle refresh failure - may need user re-authentication}// Manually refresh tokensaccount, err := scalekitClient.Actions.RefreshConnectedAccount( context.Background(), "user_123", "gmail",)if err != nil { fmt.Printf("✗ Token refresh failed: %v\n", err) // Handle refresh failure - may need user re-authentication} else { fmt.Println("✓ Tokens refreshed successfully") fmt.Printf(" Status: %s\n", account.Status)}// Manually refresh tokenstry { ConnectedAccount account = scalekitClient.actions().refreshConnectedAccount( "user_123", "gmail" ); System.out.println("✓ Tokens refreshed successfully"); System.out.println(" Status: " + account.getStatus());} catch (Exception e) { System.err.println("✗ Token refresh failed: " + e.getMessage()); // Handle refresh failure - may need user re-authentication}Token expiration handling
Section titled “Token expiration handling”Understanding how different scenarios affect token expiration:
Normal expiration cycle
Section titled “Normal expiration cycle”Timeline:
- Access token issued (expires in 1 hour)
- Scalekit monitors expiration (55 minutes elapsed)
- Automatic refresh initiated (5 minutes before expiry)
- New access token obtained (valid for 1 hour)
- Cycle repeats
Failed refresh scenarios
Section titled “Failed refresh scenarios”When refresh fails:
- Revoked refresh token: User revoked app access
- Invalid refresh token: Token became invalid or expired
- Provider errors: Temporary provider API issues
- Network issues: Connection problems during refresh
Scalekit behavior:
- Account status changes to
EXPIREDorREVOKED - Tool execution attempts return authentication errors
- You receive detailed error information
- User must re-authenticate to restore access
Handling refresh failures
Section titled “Handling refresh failures”Implement proper error handling for refresh failures:
# Execute tool with refresh failure handlingtry: result = actions.execute_tool( identifier="user_123", tool_name='gmail_send_email', tool_input={'to': 'user@example.com', 'subject': 'Hello', 'body': 'Test'} )except Exception as e: # Check if error is due to token issues if 'EXPIRED' in str(e) or 'REVOKED' in str(e): # Get fresh authorization link for user link_response = actions.get_authorization_link( connection_name="gmail", identifier="user_123" )
# Notify user to re-authenticate print(f"⚠ Please re-authenticate: {link_response.link}") # In production: send email, push notification, or in-app message else: # Handle other errors print(f"✗ Tool execution failed: {e}")// Execute tool with refresh failure handlingtry { const result = await scalekit.actions.executeTool({ identifier: 'user_123', toolName: 'gmail_send_email', toolInput: { to: 'user@example.com', subject: 'Hello', body: 'Test' } });} catch (error) { // Check if error is due to token issues if (error.message.includes('EXPIRED') || error.message.includes('REVOKED')) { // Get fresh authorization link for user const linkResponse = await scalekit.actions.getAuthorizationLink({ connectionName: 'gmail', identifier: 'user_123' });
// Notify user to re-authenticate console.log(`⚠ Please re-authenticate: ${linkResponse.link}`); // In production: send email, push notification, or in-app message } else { // Handle other errors console.error(`✗ Tool execution failed: ${error.message}`); }}// Execute tool with refresh failure handlingresult, err := scalekitClient.Actions.ExecuteTool( context.Background(), "user_123", "gmail_send_email", map[string]interface{}{ "to": "user@example.com", "subject": "Hello", "body": "Test", },)
if err != nil { // Check if error is due to token issues if strings.Contains(err.Error(), "EXPIRED") || strings.Contains(err.Error(), "REVOKED") { // Get fresh authorization link for user linkResponse, _ := scalekitClient.Actions.GetAuthorizationLink( context.Background(), "gmail", "user_123", )
// Notify user to re-authenticate fmt.Printf("⚠ Please re-authenticate: %s\n", linkResponse.Link) // In production: send email, push notification, or in-app message } else { // Handle other errors fmt.Printf("✗ Tool execution failed: %v\n", err) }}// Execute tool with refresh failure handlingtry { Map<String, Object> toolInput = new HashMap<>(); toolInput.put("to", "user@example.com"); toolInput.put("subject", "Hello"); toolInput.put("body", "Test");
ToolResult result = scalekitClient.actions().executeTool( "user_123", "gmail_send_email", toolInput );} catch (Exception e) { // Check if error is due to token issues if (e.getMessage().contains("EXPIRED") || e.getMessage().contains("REVOKED")) { // Get fresh authorization link for user AuthorizationLink linkResponse = scalekitClient.actions().getAuthorizationLink( "gmail", "user_123" );
// Notify user to re-authenticate System.out.println("⚠ Please re-authenticate: " + linkResponse.getLink()); // In production: send email, push notification, or in-app message } else { // Handle other errors System.err.println("✗ Tool execution failed: " + e.getMessage()); }}Token security
Section titled “Token security”Scalekit implements multiple security measures to protect user tokens:
Encryption
Section titled “Encryption”- At rest: All tokens encrypted using AES-256
- In transit: TLS 1.3 for all API communication
- Key management: Regular key rotation and secure storage
- Access control: Role-based access to token data
Token isolation
Section titled “Token isolation”- User isolation: Each user’s tokens stored separately
- Tenant isolation: Multi-tenant architecture with data separation
- Connection isolation: Different connections use different tokens
- Audit trail: Complete logging of token access
Compliance
Section titled “Compliance”Scalekit’s token management meets industry standards:
- SOC 2 Type II: Certified security controls
- GDPR compliant: Data protection and user privacy
- HIPAA ready: Additional security for healthcare data
- PCI DSS: Secure handling of sensitive data
Monitoring token health
Section titled “Monitoring token health”Track the health of your users’ connections and tokens:
Token metrics
Section titled “Token metrics”Monitor key metrics for connected accounts:
# Get token health metrics for monitoringaccount = actions.get_connected_account( identifier="user_123", connection_name="gmail")
# Key metrics to track:print(f"Status: {account.status}")print(f"Created: {account.created_at}")print(f"Last updated: {account.updated_at}")print(f"Scopes: {account.scopes}")
# Calculate time until re-authentication may be needed# (if using providers with expiring refresh tokens)Proactive monitoring
Section titled “Proactive monitoring”Implement monitoring to catch issues early:
- Regular status checks - Poll connected account status daily
- Error rate tracking - Monitor tool execution failures
- Refresh failure alerts - Alert on repeated refresh failures
- User notifications - Notify users proactively when re-auth needed
- Dashboard visibility - Show connection status in your app
Best practices
Section titled “Best practices”Refresh strategy
Section titled “Refresh strategy”- Trust automatic refresh: Let Scalekit handle token refresh automatically
- Check status first: Verify account status before critical operations
- Handle failures gracefully: Implement proper error handling for expired tokens
- Notify users proactively: Alert users before connections become inactive
User experience
Section titled “User experience”- Clear status indicators: Show users their connection status
- Easy re-authentication: Provide simple re-auth flows
- Graceful degradation: Handle expired tokens without breaking your app
- Helpful error messages: Explain what users need to do
Security
Section titled “Security”- Never expose tokens: Never send tokens to client applications
- Minimize token access: Limit who can access token data
- Regular audits: Review token access logs regularly
- Rotate credentials: Regularly rotate OAuth client credentials
Performance
Section titled “Performance”- Cache account status: Cache status checks appropriately (1-5 minutes)
- Batch operations: Group multiple tool executions when possible
- Async refresh: Don’t block user operations on token refresh
- Monitor latency: Track token refresh times and failures
Troubleshooting
Section titled “Troubleshooting”Common token issues
Section titled “Common token issues”Issue: Account status shows EXPIRED
- Cause: Access token expired and refresh failed
- Solution: Check refresh token validity, may need user re-authentication
Issue: Tool execution fails with authentication error
- Cause: Token invalid or revoked by user
- Solution: Generate new authorization link for user
Issue: Frequent refresh failures
- Cause: Provider API issues or invalid credentials
- Solution: Check provider status, verify OAuth credentials
Issue: User reports connection not working
- Cause: Refresh token expired (for providers with expiring refresh tokens)
- Solution: User must re-authenticate via new authorization link
Debug token issues
Section titled “Debug token issues”- Check account status - Verify connected account status
- Review error messages - Examine detailed error responses
- Check provider status - Verify third-party provider is operational
- Test manual refresh - Try manually refreshing tokens
- Verify credentials - Ensure OAuth credentials are correct
- Check scopes - Verify required scopes are granted
- Review audit logs - Check Scalekit dashboard for token events
Next steps
Section titled “Next steps”Now that you understand token management, learn about:
- Scopes and Permissions - Managing OAuth scopes and permissions
- Authentication Troubleshooting - Debugging authentication issues
- Multi-Provider Authentication - Managing multiple provider connections