Authentication Guide

# Authentication Guide This guide covers all aspects of authentication with our platform, including API key authentication, OAuth flows, and best practices for securing your applications. ## Authentication Methods Our platform supports multiple authentication methods to suit different use cases: ### 1. API Key Authentication The simplest method for server-to-server communication: ```bash curl -X POST https://api.example.com/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "api_key": "your-api-key-here" }' ``` **Response:** ```json { "success": true, "data": { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 3600 } } ``` ### 2. Bearer Token Authentication Use the access token received from login for subsequent requests: ```bash curl -X GET https://api.example.com/v1/users/me \ -H "Authorization: Bearer your-access-token" ``` ## Implementation Examples ### JavaScript/Node.js ```javascript class APIClient { constructor(apiKey) { this.apiKey = apiKey; this.accessToken = null; } async authenticate() { const response = await fetch('https://api.example.com/v1/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ api_key: this.apiKey }) }); const data = await response.json(); if (data.success) { this.accessToken = data.data.access_token; return data.data; } else { throw new Error(data.error.message); } } async makeAuthenticatedRequest(endpoint) { if (!this.accessToken) { await this.authenticate(); } const response = await fetch(`https://api.example.com/v1${endpoint}`, { headers: { 'Authorization': `Bearer ${this.accessToken}`, 'Content-Type': 'application/json' } }); return response.json(); } } // Usage const client = new APIClient('your-api-key'); const userData = await client.makeAuthenticatedRequest('/users/me'); ``` ### Python ```python import requests import json class APIClient: def __init__(self, api_key): self.api_key = api_key self.access_token = None self.base_url = "https://api.example.com/v1" def authenticate(self): response = requests.post( f"{self.base_url}/auth/login", headers={"Content-Type": "application/json"}, json={"api_key": self.api_key} ) data = response.json() if data["success"]: self.access_token = data["data"]["access_token"] return data["data"] else: raise Exception(data["error"]["message"]) def make_authenticated_request(self, endpoint): if not self.access_token: self.authenticate() response = requests.get( f"{self.base_url}{endpoint}", headers={ "Authorization": f"Bearer {self.access_token}", "Content-Type": "application/json" } ) return response.json() # Usage client = APIClient("your-api-key") user_data = client.make_authenticated_request("/users/me") ``` ## Token Management ### Token Expiration Access tokens expire after 1 hour by default. Implement token refresh logic: ```javascript class APIClient { constructor(apiKey) { this.apiKey = apiKey; this.accessToken = null; this.tokenExpiry = null; } isTokenExpired() { return !this.tokenExpiry || Date.now() >= this.tokenExpiry; } async authenticate() { const response = await fetch('https://api.example.com/v1/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ api_key: this.apiKey }) }); const data = await response.json(); if (data.success) { this.accessToken = data.data.access_token; // Set expiry time (subtract 5 minutes for safety) this.tokenExpiry = Date.now() + (data.data.expires_in - 300) * 1000; return data.data; } else { throw new Error(data.error.message); } } async makeAuthenticatedRequest(endpoint) { if (this.isTokenExpired()) { await this.authenticate(); } // ... rest of the request logic } } ``` ### Secure Token Storage **Server-side (Node.js):** ```javascript // Use environment variables const apiKey = process.env.API_KEY; // For session storage req.session.accessToken = token; // For database storage (encrypted) const encryptedToken = await encrypt(token, encryptionKey); await db.tokens.create({ userId, token: encryptedToken }); ``` **Client-side (Browser):** ```javascript // Store in memory (cleared on page refresh) let accessToken = null; // For persistent storage (less secure) localStorage.setItem('accessToken', token); // For session storage (cleared when tab closes) sessionStorage.setItem('accessToken', token); ``` ## Error Handling Handle authentication errors gracefully: ```javascript async function handleAuthError(error) { switch (error.code) { case 'INVALID_API_KEY': console.error('API key is invalid. Please check your configuration.'); break; case 'TOKEN_EXPIRED': console.log('Token expired, refreshing...'); await authenticate(); break; case 'RATE_LIMITED': console.error('Rate limit exceeded. Please wait before retrying.'); break; default: console.error('Authentication error:', error.message); } } // Usage in request try { const response = await makeAuthenticatedRequest('/users/me'); return response; } catch (error) { await handleAuthError(error); throw error; } ``` ## Security Best Practices ### 1. API Key Security - **Never expose API keys in client-side code** - Store keys in environment variables - Rotate keys regularly - Use different keys for development and production ### 2. Token Security - Store tokens securely (encrypted if possible) - Implement token expiration handling - Clear tokens on logout - Use HTTPS for all API calls ### 3. Rate Limiting ```javascript class RateLimiter { constructor(maxRequests = 100, windowMs = 60000) { this.maxRequests = maxRequests; this.windowMs = windowMs; this.requests = []; } async checkLimit() { const now = Date.now(); this.requests = this.requests.filter(time => now - time < this.windowMs); if (this.requests.length >= this.maxRequests) { throw new Error('Rate limit exceeded'); } this.requests.push(now); } } ``` ### 4. Request Validation ```javascript function validateRequest(data) { const required = ['api_key']; const missing = required.filter(field => !data[field]); if (missing.length > 0) { throw new Error(`Missing required fields: ${missing.join(', ')}`); } if (data.api_key.length < 32) { throw new Error('API key appears to be invalid'); } } ``` ## Testing Authentication ### Unit Tests ```javascript describe('Authentication', () => { test('should authenticate with valid API key', async () => { const client = new APIClient('valid-api-key'); const result = await client.authenticate(); expect(result.access_token).toBeDefined(); expect(result.token_type).toBe('Bearer'); }); test('should handle invalid API key', async () => { const client = new APIClient('invalid-key'); await expect(client.authenticate()).rejects.toThrow('Invalid API key'); }); }); ``` ### Integration Tests ```javascript describe('API Integration', () => { test('should make authenticated requests', async () => { const client = new APIClient(process.env.TEST_API_KEY); const userData = await client.makeAuthenticatedRequest('/users/me'); expect(userData.success).toBe(true); expect(userData.data.id).toBeDefined(); }); }); ``` ## Troubleshooting ### Common Issues 1. **"Invalid API Key" Error** - Verify the API key is correct - Check for extra spaces or characters - Ensure the key is active in your dashboard 2. **"Token Expired" Error** - Implement automatic token refresh - Check system clock synchronization - Verify token expiration handling 3. **"Rate Limited" Error** - Implement exponential backoff - Reduce request frequency - Check your rate limit quotas ### Debug Mode Enable debug logging for troubleshooting: ```javascript const DEBUG = process.env.NODE_ENV === 'development'; function log(message, data = null) { if (DEBUG) { console.log(`[Auth] ${message}`, data); } } ``` ## Next Steps After implementing authentication: - Set up user management and permissions - Implement OAuth flows if needed - Add multi-factor authentication - Configure webhook authentication For more information, check out our [API Reference](/api-docs) and [Security Guide](/docs/guides/security).

Get in Touch