Skip to content

Security & Authentication


Overview

Traylinx uses a dual-token authentication model designed for secure agent-to-agent (A2A) communication while maintaining backward compatibility with user authentication.


The Dual-Token Model

Token Purpose Used For Header
access_token Authenticate with Sentinel Auth service calls only Authorization: Bearer
agent_secret_token Prove identity to other agents A2A communication X-Agent-Secret-Token

Why Two Tokens?

PROBLEM: If stolen, a single token could impersonate an agent anywhere.

SOLUTION: Agent Secret Token is cryptographically bound to the agent's client_secret.
          Only the legitimate owner can generate valid tokens.

Agent Secret Token Cryptography

Generation Flow

1. Agent authenticates → POST /oauth/token
   ├─ Input: client_id, client_secret
   └─ Output: access_token + agent_secret_token

2. Agent Secret Token Structure:
   ┌──────────────────────────────────────────────────┐
   │ AgentSecretToken_<nonce>_<encrypted_payload>     │
   └──────────────────────────────────────────────────┘
   Encrypted with: PBKDF2(client_secret) → AES-256-GCM

Security Guarantees

Attack Protection
Token Interception AES-256-GCM encryption
Token Forgery 128-bit authentication tags
Replay Attack Timestamp + nonce + 1hr expiry
Brute Force PBKDF2 with 10,000+ iterations
Man-in-the-Middle TLS 1.3 required

Authentication Flows

Flow 1: Agent-to-Agent (A2A)

Agent A                           Agent B
   │                                 │
   │  Headers:                       │
   │  X-Agent-Secret-Token: xxx      │
   │  X-Agent-User-Id: agent-a       │
   │  Content-Type: application/     │
   │    vnd.traylinx.a2a+json        │
   │─────────────────────────────────▶
   │                                 │
   │                                 │ 1. Extract token
   │                                 │ 2. Validate via Sentinel
   │                                 │ 3. Process request
   │◀─────────────────────────────────

Flow 2: User-to-Service

User App                          Service
   │                                 │
   │  Headers:                       │
   │  Authorization: Bearer xxx      │
   │─────────────────────────────────▶
   │                                 │
   │                                 │ 1. Extract token
   │                                 │ 2. Validate via Auth Service
   │                                 │ 3. Get user from DB
   │◀─────────────────────────────────

Flow 3: Unified (Dual-Auth)

Services can accept both authentication types using our unified middleware:

from middleware.unified_auth import UnifiedAuthMiddleware, AuthMode

# Detection logic:
# - If X-Agent-Secret-Token present → AGENT mode
# - If Authorization: Bearer present → USER mode

@app.post("/api/task")
async def task_endpoint(auth: CallerIdentity = Depends(get_caller_identity)):
    if auth.mode == AuthMode.AGENT:
        print(f"Called by agent: {auth.agent_id}")
    else:
        print(f"Called by user: {auth.user_id}")

Service Authentication Status

Production Status (as of 2025-12-07)

Service User Auth Agent Auth Implementation
Agent Registry N/A @require_a2a_auth
Router Agent N/A @require_a2a_auth
Subscription Service N/A @require_a2a_auth
Cortex ✅ DB ✅ Sentinel get_caller_identity()
Agent Template ✅ API Key ✅ Sentinel verify_unified_auth()
Agentic Search ✅ Bearer ✅ Sentinel UnifiedAuthMiddleware
Agentic Translation ✅ Bearer ✅ Sentinel UnifiedAuthMiddleware
Agentic Upload ✅ Bearer ✅ Sentinel UnifiedAuthMiddleware

Quick Reference: Adding Auth to Your Service

Option 1: Agent-Only (Simplest)

from traylinx_auth_client import require_a2a_auth

@router.post("/a2a/task")
@require_a2a_auth
async def agent_only_endpoint(request: Request):
    agent_id = request.headers.get("x-agent-user-id")
    return {"called_by": agent_id}
from traylinx_auth_client import require_dual_auth, detect_auth_mode

@router.post("/api/task")
@require_dual_auth
async def unified_endpoint(request: Request):
    mode = detect_auth_mode(request.headers)
    # mode is "agent" or "user"
    return {"auth_mode": mode}

Option 3: Full Middleware (Maximum Control)

See unified_auth.py for the complete implementation.


Environment Variables

All services using Sentinel auth require:

TRAYLINX_CLIENT_ID=your-agent-id
TRAYLINX_CLIENT_SECRET=your-secret
TRAYLINX_API_BASE_URL=https://api.makakoo.com/ma-authentication-ms/v1/api
TRAYLINX_AGENT_USER_ID=your-agent-id

Security Best Practices

  1. Never log tokens — Use masked versions: token[:8]...
  2. Always use HTTPS — TLS 1.3 is required
  3. Rotate secrets regularly — Implement key rotation
  4. Rate limit endpoints — Prevent brute-force attacks
  5. Monitor activity — Use Sentinel's activity logging