Authentication
Learn about Devcogent's authentication methods and how to secure your API requests.
Authentication Methods
Devcogent supports multiple authentication methods to suit different use cases:
API Key Authentication
The simplest method for server-to-server communication:
const headers = {
'Authorization': `Bearer your-api-key-here`,
'Content-Type': 'application/json'
};
const response = await fetch('https://api.devcogent.com/v1/users', {
headers: headers
});
OAuth 2.0
For applications that need to act on behalf of users:
Authorization Code Flow
- Redirect user to authorization URL:
const authUrl = `https://auth.devcogent.com/oauth/authorize?` +
`client_id=${clientId}&` +
`redirect_uri=${redirectUri}&` +
`response_type=code&` +
`scope=read write&` +
`state=${randomState}`;
window.location.href = authUrl;
- Exchange authorization code for access token:
const tokenResponse = await fetch('https://auth.devcogent.com/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
grant_type: 'authorization_code',
client_id: clientId,
client_secret: clientSecret,
code: authorizationCode,
redirect_uri: redirectUri
})
});
const tokens = await tokenResponse.json();
// tokens.access_token, tokens.refresh_token
- Use access token for API requests:
const apiResponse = await fetch('https://api.devcogent.com/v1/user', {
headers: {
'Authorization': `Bearer ${tokens.access_token}`
}
});
JWT Tokens
For service-to-service authentication:
import jwt from 'jsonwebtoken';
const payload = {
iss: 'your-service-id',
aud: 'devcogent-api',
sub: 'service-account',
exp: Math.floor(Date.now() / 1000) + 3600 // 1 hour
};
const token = jwt.sign(payload, privateKey, { algorithm: 'RS256' });
const response = await fetch('https://api.devcogent.com/v1/resources', {
headers: {
'Authorization': `Bearer ${token}`
}
});
Managing API Keys
Creating API Keys
- Log in to your Devcogent dashboard
- Navigate to Settings > API Keys
- Click Generate New Key
- Choose permissions and expiration
- Copy and securely store your key
API Key Permissions
Configure fine-grained permissions for your API keys:
{
"permissions": {
"resources": ["read", "write", "delete"],
"users": ["read"],
"webhooks": ["read", "write"]
},
"rate_limits": {
"requests_per_minute": 100
},
"ip_whitelist": ["192.168.1.1", "10.0.0.0/8"]
}
Rotating API Keys
Regular key rotation for security:
// 1. Generate new key via dashboard or API
const newKey = await generateNewApiKey({
name: 'Production Key v2',
permissions: currentPermissions
});
// 2. Update your application configuration
process.env.DEVCOGENT_API_KEY = newKey.key;
// 3. Verify new key works
await testApiConnection(newKey.key);
// 4. Revoke old key
await revokeApiKey(oldKeyId);
Token Management
Access Token Refresh
Automatically refresh expired tokens:
class DevcogentAuth {
constructor(clientId, clientSecret, refreshToken) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.refreshToken = refreshToken;
this.accessToken = null;
this.tokenExpiry = null;
}
async getValidToken() {
if (this.accessToken && Date.now() < this.tokenExpiry) {
return this.accessToken;
}
return await this.refreshAccessToken();
}
async refreshAccessToken() {
const response = await fetch('https://auth.devcogent.com/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'refresh_token',
client_id: this.clientId,
client_secret: this.clientSecret,
refresh_token: this.refreshToken
})
});
const tokens = await response.json();
this.accessToken = tokens.access_token;
this.tokenExpiry = Date.now() + (tokens.expires_in * 1000);
return this.accessToken;
}
}
Token Storage
Secure token storage practices:
// Browser (using secure storage)
class TokenStorage {
static setTokens(tokens) {
// Store in httpOnly cookies or secure storage
document.cookie = `access_token=${tokens.access_token}; Secure; HttpOnly; SameSite=Strict`;
localStorage.setItem('token_expiry', tokens.expires_at);
}
static getAccessToken() {
// Retrieve from secure storage
return getCookieValue('access_token');
}
}
// Node.js (using environment variables or key management)
class ServerTokenStorage {
static setTokens(tokens) {
// Store in environment variables or key management service
process.env.DEVCOGENT_ACCESS_TOKEN = tokens.access_token;
process.env.DEVCOGENT_REFRESH_TOKEN = tokens.refresh_token;
}
}
Security Best Practices
Environment-Specific Keys
Use different API keys for different environments:
const getApiKey = () => {
switch (process.env.NODE_ENV) {
case 'development':
return process.env.DEVCOGENT_DEV_API_KEY;
case 'staging':
return process.env.DEVCOGENT_STAGING_API_KEY;
case 'production':
return process.env.DEVCOGENT_PROD_API_KEY;
default:
throw new Error('Unknown environment');
}
};
Request Signing
Add an extra layer of security with request signing:
import crypto from 'crypto';
function signRequest(method, path, body, timestamp, secret) {
const payload = `${method}\n${path}\n${body}\n${timestamp}`;
return crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
}
const timestamp = Date.now().toString();
const signature = signRequest('POST', '/v1/resources', requestBody, timestamp, apiSecret);
const headers = {
'Authorization': `Bearer ${apiKey}`,
'X-Devcogent-Timestamp': timestamp,
'X-Devcogent-Signature': signature,
'Content-Type': 'application/json'
};
IP Whitelisting
Restrict API access to specific IP addresses:
// Configure IP whitelist in dashboard or via API
const apiKeyConfig = {
name: 'Production API Key',
permissions: ['read', 'write'],
ip_whitelist: [
'192.168.1.100', // Specific IP
'10.0.0.0/24', // CIDR range
'2001:db8::/32' // IPv6 range
]
};
Error Handling
Handle authentication errors gracefully:
async function makeAuthenticatedRequest(url, options = {}) {
try {
const response = await fetch(url, {
...options,
headers: {
'Authorization': `Bearer ${await getValidToken()}`,
...options.headers
}
});
if (response.status === 401) {
// Token expired or invalid
await refreshToken();
return makeAuthenticatedRequest(url, options); // Retry once
}
if (response.status === 403) {
throw new Error('Insufficient permissions for this operation');
}
return response;
} catch (error) {
console.error('Authentication error:', error);
throw error;
}
}
Testing Authentication
Test your authentication implementation:
// Test API key validity
async function testApiKey(apiKey) {
try {
const response = await fetch('https://api.devcogent.com/v1/auth/test', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
if (response.ok) {
console.log('API key is valid');
return true;
} else {
console.error('API key is invalid or expired');
return false;
}
} catch (error) {
console.error('Error testing API key:', error);
return false;
}
}
// Test OAuth flow
async function testOAuthFlow() {
// Implementation for testing OAuth flow
const authUrl = buildAuthUrl();
console.log('Visit this URL to authorize:', authUrl);
// After authorization, test token exchange
const tokens = await exchangeCodeForTokens(authCode);
console.log('Tokens received:', !!tokens.access_token);
}
Troubleshooting
Common authentication issues:
Invalid API Key
- Verify the key is correct and hasn't been revoked
- Check if the key has expired
- Ensure proper permissions are set
Token Expired
- Implement automatic token refresh
- Check token expiration times
- Handle 401 responses appropriately
OAuth Redirect Issues
- Verify redirect URI matches exactly
- Check for HTTPS requirements
- Validate state parameter for security
Rate Limiting
- Check if you're exceeding API limits
- Implement exponential backoff for retries
- Consider upgrading your plan for higher limits
Next Steps
- Learn about API Integration
- Set up Deployment with proper authentication
- Review Troubleshooting for common issues