Skip to main content

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

  1. 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;
  1. 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
  1. 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

  1. Log in to your Devcogent dashboard
  2. Navigate to Settings > API Keys
  3. Click Generate New Key
  4. Choose permissions and expiration
  5. 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