OAuth 1.0a Signer

OAuth 1.0a Signer

The agentsec-signer crate is a standalone sidecar that signs requests with OAuth 1.0a (HMAC-SHA1, RFC 5849). Use it for APIs that require OAuth 1.0a authentication, like the Twitter/X API.

How It Works

AgentSec Proxy                  OAuth Signer               Twitter API
     │                               │                          │
     │  POST /                       │                          │
     │  X-OAuth-Credential: twitter  │                          │
     │  X-OAuth-Target: https://...  │                          │
     │  X-AgentSec-Method: POST      │                          │
     │  body: {"text":"Hello"}       │                          │
     │ ─────────────────────────────>│                          │
     │                               │  Signs with HMAC-SHA1   │
     │                               │  POST https://...        │
     │                               │  Authorization: OAuth .. │
     │                               │ ────────────────────────>│
     │                               │                          │
     │                               │  Response               │
     │                <──────────────│<─────────────────────────│
  1. Receives a request with X-OAuth-Credential (credential name) and X-OAuth-Target (real API URL)
  2. Loads the credential’s consumer key, consumer secret, access token, and access token secret from env vars
  3. Builds an OAuth 1.0a signature (nonce, timestamp, signature base string, HMAC-SHA1)
  4. Forwards the request to the real API with the signed Authorization header
  5. Returns the upstream response (auth headers stripped)

Setup

1. Set Environment Variables

Each credential requires four env vars following this pattern:

OAUTH_CRED_{NAME}_CONSUMER_KEY=your-consumer-key
OAUTH_CRED_{NAME}_CONSUMER_SECRET=your-consumer-secret
OAUTH_CRED_{NAME}_ACCESS_TOKEN=your-access-token
OAUTH_CRED_{NAME}_ACCESS_TOKEN_SECRET=your-access-token-secret

The signer auto-discovers credentials by scanning for OAUTH_CRED_*_CONSUMER_KEY env vars at startup.

Example for Twitter:

OAUTH_CRED_TWITTER_CONSUMER_KEY=xvz1evFS4wEEPTGEFPHBog
OAUTH_CRED_TWITTER_CONSUMER_SECRET=kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw
OAUTH_CRED_TWITTER_ACCESS_TOKEN=370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb
OAUTH_CRED_TWITTER_ACCESS_TOKEN_SECRET=LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE

2. Configure AgentSec

In agentsec.yaml, set up the credential with connector: sidecar pointing at the signer:

credentials:
  twitter:
    description: "Twitter API v2"
    connector: sidecar
    api_base: "http://oauth-signer:8080"
 
policies:
  twitter:
    auto_approve: ["GET"]
    require_approval: ["POST", "PUT", "DELETE"]

3. Add to Docker Compose

services:
  oauth-signer:
    build:
      context: .
      dockerfile: Dockerfile.signer  # or use the same Dockerfile with different target
    ports:
      - "8080:8080"
    environment:
      - OAUTH_SIGNER_PORT=8080
      - OAUTH_CRED_TWITTER_CONSUMER_KEY
      - OAUTH_CRED_TWITTER_CONSUMER_SECRET
      - OAUTH_CRED_TWITTER_ACCESS_TOKEN
      - OAUTH_CRED_TWITTER_ACCESS_TOKEN_SECRET

4. Test

# Check signer health (lists discovered credentials)
curl http://localhost:8080/health
 
# Post a tweet through AgentSec
curl -X POST http://localhost:3100/forward \
  -H "X-AgentSec-Key: $MY_AGENT_KEY" \
  -H "X-AgentSec-Credential: twitter" \
  -H "X-AgentSec-Target: https://api.twitter.com/2/tweets" \
  -H "X-AgentSec-Method: POST" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello from AgentSec!"}'

Signer API

EndpointMethodDescription
/ANYSign and forward request. Requires X-OAuth-Credential and X-OAuth-Target headers
/healthGETHealth check, returns list of loaded credentials

Port: Configurable via OAUTH_SIGNER_PORT (default 8080).

The X-AgentSec-Method header tells the signer which HTTP method to use for signing and forwarding (since the proxy always sends via POST).