Using API Keys
API keys provide a simple way to authenticate server-to-server requests to the Agglestone Authentication and User Management Service. Unlike JWT tokens, API keys are long-lived credentials that don’t expire, making them perfect for background services, scheduled jobs, and automated processes.
> ⚠️ Important: API keys are powerful credentials that provide system-level access to your tenant. If an API key is exposed — for example, if it’s accidentally committed to a Git repository, exposed in logs, or shared insecurely — an attacker could gain full access to your tenant’s resources. Always store API keys securely and never commit them to version control.
Why Use API Keys?
API keys offer several advantages for server-to-server communication:
- Long-Lived: No token refresh logic needed — use the same key until you rotate it
- Server-to-Server: Designed for automated processes and background services
- Key Rotation: Primary and secondary keys allow for zero-downtime key rotation
- System-Level Access: Perfect for administrative operations and system integrations
Getting Your API Keys
API keys are managed through the Agglestone Portal at https://portal.agglestone.com. Once you log in, you can:
- View your current primary and secondary API keys
- Generate new API keys (which automatically invalidates the previous key of the same type)
- Rotate keys without service interruption by using the secondary key during rotation
Each tenant has both a primary and secondary API key. This allows you to rotate keys without downtime: generate a new primary key while keeping the secondary active, then switch your services to use the new key.
How API Keys Work
API keys are sent in the X-API-Key header with every request to the Agglestone Authentication and User Management Service. The service validates the key and grants access based on the tenant associated with that key.
Unlike JWT tokens, API keys don’t contain user information. They provide system-level access to your tenant’s resources. If you need to make requests on behalf of a specific user, you can exchange your API key for a JWT token using the token exchange endpoint.
Implementation Examples
Here are examples of how to use API keys in common backend frameworks. All examples use standard HTTP client libraries that are built into or commonly used with these frameworks.
Recommended libraries and frameworks:
- C# / ASP.NET Core: Built-in
HttpClientorIHttpClientFactory - Node.js: Built-in
fetch(Node.js 18+) oraxios - Python:
httpxorrequests
// Add the code below to your service or controller
// Using HttpClient with IHttpClientFactory (recommended for ASP.NET Core)
using System.Net.Http.Headers;
public class AgglestoneApiService
{
private readonly HttpClient _httpClient;
private readonly string _tenantId;
private readonly string _apiKey;
public AgglestoneApiService(IHttpClientFactory httpClientFactory, IConfiguration configuration)
{
_httpClient = httpClientFactory.CreateClient();
_tenantId = configuration["Agglestone:TenantId"]; // Get from https://portal.agglestone.com
_apiKey = configuration["Agglestone:ApiKey"]; // Get from https://portal.agglestone.com
_httpClient.BaseAddress = new Uri($"https://auth.agglestone.com/tenant/{_tenantId}/");
_httpClient.DefaultRequestHeaders.Add("X-API-Key", _apiKey);
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<string> GetUsersAsync()
{
var response = await _httpClient.GetAsync("api/v2.0/Users");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
// Add the code below to your service or module
// Using fetch (Node.js 18+) or axios
const tenantId = 'your-tenant-id'; // Get from https://portal.agglestone.com
const apiKey = 'your-api-key'; // Get from https://portal.agglestone.com
const baseUrl = `https://auth.agglestone.com/tenant/${tenantId}/`;
async function getUsers() {
const response = await fetch(`${baseUrl}api/v2.0/Users`, {
method: 'GET',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
// Example usage
getUsers()
.then(users => console.log(users))
.catch(error => console.error('Error:', error));
# Install: httpx or requests
# Add the code below to your service or module
import httpx
tenant_id = "your-tenant-id" # Get from https://portal.agglestone.com
api_key = "your-api-key" # Get from https://portal.agglestone.com
base_url = f"https://auth.agglestone.com/tenant/{tenant_id}/"
async def get_users():
async with httpx.AsyncClient() as client:
response = await client.get(
f"{base_url}api/v2.0/Users",
headers={
"X-API-Key": api_key,
"Content-Type": "application/json"
}
)
response.raise_for_status()
return response.json()
# Example usage
import asyncio
users = asyncio.run(get_users())
print(users)
Exchanging API Keys for JWT Tokens
If you need to make requests on behalf of a specific user, you can exchange your API key for a JWT token. This is useful when you need user context for certain operations.
The token exchange endpoint accepts your API key in the X-API-Key header and a userId in the request body, then returns a JWT token that represents that user. This token can then be used for subsequent API calls that require user context.
// Exchange API key for JWT token
public async Task<string> ExchangeApiKeyForTokenAsync(string userId)
{
var request = new
{
userId = userId
};
var response = await _httpClient.PostAsJsonAsync("v2.0/Auth/token-exchange", request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<dynamic>();
return result.token; // Use this JWT token for subsequent requests
}
// Exchange API key for JWT token
async function exchangeApiKeyForToken(userId) {
const response = await fetch(`${baseUrl}v2.0/Auth/token-exchange`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
userId: userId
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
return result.token; // Use this JWT token for subsequent requests
}
# Exchange API key for JWT token
async def exchange_api_key_for_token(user_id):
async with httpx.AsyncClient() as client:
response = await client.post(
f"{base_url}v2.0/Auth/token-exchange",
headers={
"X-API-Key": api_key,
"Content-Type": "application/json"
},
json={
"userId": user_id
}
)
response.raise_for_status()
result = response.json()
return result["token"] # Use this JWT token for subsequent requests
Key Rotation Best Practices
When rotating API keys, follow these best practices:
- Use Secondary Key During Rotation: Generate a new primary key while your services are still using the secondary key
- Update Services Gradually: Update your services to use the new primary key one at a time
- Keep Secondary as Backup: Once all services are using the new primary key, generate a new secondary key as a backup
- Store Keys Securely: Never commit API keys to version control. Use environment variables, secret management services, or secure configuration stores
- Monitor Key Usage: Keep track of which services are using which keys to make rotation easier
Important Security Considerations
> ⚠️ Warning: API keys are powerful credentials that provide system-level access to your tenant. If an API key falls into the wrong hands—for example, if it’s accidentally committed to a public Git repository, exposed in logs, or shared insecurely—an attacker could gain full access to your tenant’s resources. Always treat API keys with extreme care and follow security best practices.
When using API keys:
- Never Use from Frontend: API keys must never be used in frontend applications, browser-based code, or client-side JavaScript. Anyone can view the source code of frontend applications, making API keys immediately visible and compromising your security. API keys should only be used in backend services, server-side code, and secure server environments
- Store Keys Securely: Use environment variables, secret management services, or secure configuration stores—never hardcode keys in your source code or commit them to version control
- Use HTTPS: Always use HTTPS in production to protect keys in transit
- Rotate Immediately if Compromised: If you suspect an API key has been exposed, rotate it immediately through the Agglestone Portal
- Rotate Regularly: Regularly rotate your API keys as part of your security practices, even if there’s no suspicion of compromise
- Limit Key Scope: API keys provide system-level access—ensure only trusted services have access to them
- Monitor Usage: Monitor API key usage to detect any unauthorized access or unusual patterns
- Never Share Keys: Never share API keys via email, chat, or other insecure channels
API keys are powerful credentials that provide system-level access to your tenant. Treat them with the same security care you would any other sensitive credential, and be aware that exposure of an API key could lead to unauthorized access to your entire tenant.
> 📚 API Documentation: For detailed API documentation, request/response schemas, and to try out the endpoints interactively, visit the Swagger UI.
—
Ready to learn more? Check out the Quick Start Guide to see how to get authentication working in your frontend, or learn about Validating JWTs in Your Backend for user authentication.