Configure Autonomous Workload
Learn how to set up machine identities and configure autonomous agents for secure M2M authentication.
Prerequisites
Before configuring an autonomous workload, ensure you have:
- AuthSec workspace created
- Admin access to your workspace
- Application/service that needs M2M authentication
Step 1: Create a Client Application
First, register your autonomous agent as a client in AuthSec.
Via AuthSec Dashboard
- Navigate to Administration → Clients
- Click "Create Client"
- Fill in the details:
| Field | Description | Example |
|---|---|---|
| Client Name | Human-readable name | ml-training-agent |
| Client Type | Select Machine-to-Machine | M2M |
| Description | Purpose of this workload | "ML model training service" |
- Click "Create Client"
Important Configuration Options
Grant Type: Client Credentials
Enables OAuth 2.0 service authentication
Token Lifetime:
- Recommended: 1-24 hours
- Shorter = more secure, but more token requests
Allowed Scopes:
Define what resources this workload can access
Step 2: Obtain Client Credentials
After creating the client, AuthSec generates:
Client ID
client_abc123xyz789
Unique identifier for your workload (safe to share)
Client Secret
secret_def456uvw012_NEVER_SHARE_THIS
Secret key (treat like a password - never commit to Git!)
Save the client secret immediately! It's shown only once. If lost, you must regenerate it.
Step 3: Configure Your Application
Environment Variables (Recommended)
Store credentials securely using environment variables:
export AUTHSEC_CLIENT_ID="client_abc123xyz789"
export AUTHSEC_CLIENT_SECRET="secret_def456uvw012"
export AUTHSEC_TOKEN_URL="https://auth.authsec.ai/oauth/token"
Configuration File Example
config.yaml
authsec:
client_id: ${AUTHSEC_CLIENT_ID}
client_secret: ${AUTHSEC_CLIENT_SECRET}
token_url: https://auth.authsec.ai/oauth/token
scopes:
- read:data
- write:logs
Use environment variables or secret managers (AWS Secrets Manager, HashiCorp Vault) instead of hard-coding credentials.
Step 4: Implement Authentication Flow
OAuth 2.0 Client Credentials Flow
Here's how your workload obtains access tokens:
1. Request Access Token
HTTP Request:
POST https://auth.authsec.ai/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=client_abc123xyz789
&client_secret=secret_def456uvw012
&scope=read:data write:logs
2. Receive Access Token
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read:data write:logs"
}
3. Use Token for API Requests
HTTP Request:
GET https://api.yourservice.com/data
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Step 5: Code Examples
Python
import requests
import os
# Configuration
CLIENT_ID = os.getenv('AUTHSEC_CLIENT_ID')
CLIENT_SECRET = os.getenv('AUTHSEC_CLIENT_SECRET')
TOKEN_URL = 'https://auth.authsec.ai/oauth/token'
def get_access_token():
"""Request access token from AuthSec"""
response = requests.post(TOKEN_URL, data={
'grant_type': 'client_credentials',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'scope': 'read:data write:logs'
})
response.raise_for_status()
return response.json()['access_token']
def call_protected_api():
"""Use access token to call protected API"""
token = get_access_token()
headers = {
'Authorization': f'Bearer {token}'
}
response = requests.get(
'https://api.yourservice.com/data',
headers=headers
)
return response.json()
# Use in your application
if __name__ == '__main__':
data = call_protected_api()
print(data)
Node.js
const axios = require('axios');
const CLIENT_ID = process.env.AUTHSEC_CLIENT_ID;
const CLIENT_SECRET = process.env.AUTHSEC_CLIENT_SECRET;
const TOKEN_URL = 'https://auth.authsec.ai/oauth/token';
async function getAccessToken() {
const response = await axios.post(TOKEN_URL, new URLSearchParams({
grant_type: 'client_credentials',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
scope: 'read:data write:logs'
}));
return response.data.access_token;
}
async function callProtectedApi() {
const token = await getAccessToken();
const response = await axios.get('https://api.yourservice.com/data', {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.data;
}
// Use in your application
callProtectedApi()
.then(data => console.log(data))
.catch(error => console.error(error));
Go
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
type TokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
}
func getAccessToken() (string, error) {
clientID := os.Getenv("AUTHSEC_CLIENT_ID")
clientSecret := os.Getenv("AUTHSEC_CLIENT_SECRET")
data := url.Values{}
data.Set("grant_type", "client_credentials")
data.Set("client_id", clientID)
data.Set("client_secret", clientSecret)
data.Set("scope", "read:data write:logs")
resp, err := http.PostForm("https://auth.authsec.ai/oauth/token", data)
if err != nil {
return "", err
}
defer resp.Body.Close()
var tokenResp TokenResponse
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
return "", err
}
return tokenResp.AccessToken, nil
}
func callProtectedApi() ([]byte, error) {
token, err := getAccessToken()
if err != nil {
return nil, err
}
req, err := http.NewRequest("GET", "https://api.yourservice.com/data", nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
func main() {
data, err := callProtectedApi()
if err != nil {
panic(err)
}
fmt.Println(string(data))
}
Step 6: Token Caching & Rotation
Best Practices
Cache Tokens
Don't request a new token for every API call. Reuse until expiration.
Implement Refresh Logic
Check token expiration and refresh before it expires:
import time
class TokenManager:
def __init__(self):
self.token = None
self.expires_at = 0
def get_token(self):
now = time.time()
# Refresh if token expires in < 5 minutes
if now >= (self.expires_at - 300):
self.refresh_token()
return self.token
def refresh_token(self):
response = get_access_token()
self.token = response['access_token']
self.expires_at = time.time() + response['expires_in']
Handle Errors Gracefully
Retry with exponential backoff if token request fails.
Step 7: Verify Configuration
Test Your Setup
-
Request a token
curl -X POST https://auth.authsec.ai/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=read:data" -
Verify token is valid JWT
- Copy the
access_tokenfrom response - Paste into jwt.io to inspect claims
- Copy the
-
Test API access
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://api.yourservice.com/data
Security Best Practices
Never Hard-Code Secrets
✗ Bad: client_secret: "abc123"
✓ Good: client_secret: ${AUTHSEC_CLIENT_SECRET}
Rotate Credentials Regularly
Change client secrets every 90 days minimum
Use Minimal Scopes
Only request necessary permissions
Monitor Token Usage
Review AuthSec logs for unusual activity
Secure Storage
Use secret managers or encrypted vaults
Troubleshooting
"Invalid client credentials"
Cause: Wrong client ID or secret
Fix: Verify credentials match AuthSec dashboard
"Insufficient scope"
Cause: Token doesn't have required permissions
Fix: Add necessary scopes when requesting token
Token expires too quickly
Cause: Short token lifetime setting
Fix: Adjust token lifetime in AuthSec client configuration
Next Steps
Your autonomous workload is now configured! For production deployments with automatic certificate rotation, integrate SPIRE:
Or explore advanced security patterns: