Skip to main content

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

  1. Navigate to AdministrationClients
  2. Click "Create Client"
  3. Fill in the details:
FieldDescriptionExample
Client NameHuman-readable nameml-training-agent
Client TypeSelect Machine-to-MachineM2M
DescriptionPurpose of this workload"ML model training service"
  1. 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!)

Important

Save the client secret immediately! It's shown only once. If lost, you must regenerate it.


Step 3: Configure Your Application

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
Best Practice

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

  1. 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"
  2. Verify token is valid JWT

    • Copy the access_token from response
    • Paste into jwt.io to inspect claims
  3. 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:

Integrate SPIRE →

Or explore advanced security patterns:

Security Best Practices →