Skip to main content

Gateway Authentication

The Gateway supports multiple authentication methods to accommodate different client types and security requirements.

Authentication Methods

MethodUse CaseHeader Format
API KeyThird-party integrationsAuthorization: Bearer olive_live_xxx
JWTAdmin dashboard, internal UIAuthorization: Bearer eyJ...
Service AuthInternal services (Agent-TS)X-Service-Name, X-Service-Timestamp, X-Service-Signature
POS HMACMerchant terminalsX-API-Key-ID, X-Timestamp, X-Signature
Partner HMACPartner integrationsX-API-Key-ID, X-Partner-ID, X-Timestamp, X-Signature

API Key Authentication

For third-party integrations and external clients.

Header Format

Authorization: Bearer olive_live_xxxxxxxxxxxxxxxxxxxxxxxx

API Key Structure

PrefixEnvironment
olive_live_Production
olive_test_Staging/Testing

Creating API Keys

Admin users can create API keys via the admin endpoint:
curl -X POST http://localhost:8080/api/v1/admin/api-keys \
  -H "Authorization: Bearer ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Partner Integration",
    "scopes": ["payments:read", "payments:write", "balance:read"],
    "expires_at": "2025-12-31T23:59:59Z"
  }'

API Key Scopes

ScopeDescription
payments:readRead transaction history
payments:writeCreate payments and transfers
balance:readRead account balances
subscribers:readRead subscriber information
subscribers:writeCreate and update subscribers
cards:readList cards
cards:writeLink/block cards

JWT Authentication

For admin users and internal dashboards.

Obtaining a JWT

curl -X POST http://localhost:8080/api/v1/admin/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@olive.example.com",
    "password": "secure-password"
  }'
Response:
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 86400
}

Using JWT

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

JWT Claims

{
  "sub": "admin-user-id",
  "email": "admin@olive.example.com",
  "role": "system_admin",
  "iat": 1704067200,
  "exp": 1704153600
}

Admin Roles

RolePermissions
system_adminFull access to all operations
compliance_userCompliance alerts and monitoring
support_userRead-only access, basic support ops
finance_userTransaction and reconciliation access

Service Authentication

For internal service-to-service communication (e.g., Agent-TS to Gateway).

Headers

X-Service-Name: gateway
X-Service-Timestamp: 1710072000
X-Service-Signature: <hex-hmac>

Signature Generation

import crypto from 'crypto';

function generateServiceHeaders(
  method: string,
  path: string,
  query: string,
  secret: string,
  timestamp: string,
  serviceName: string
) {
  const payload = `${method}|${path}|${query}|${timestamp}`;
  const signature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return {
    'X-Service-Name': serviceName,
    'X-Service-Timestamp': timestamp,
    'X-Service-Signature': signature,
  };
}

// Usage
const timestamp = Math.floor(Date.now() / 1000).toString();
const headers = generateServiceHeaders(
  'POST',
  '/api/v1/compliance/alerts',
  '',
  process.env.AGENT_TS_SECRET,
  timestamp,
  'agent-ts'
);

Configuration

In config.yaml:
service_auth:
  agent_ts:
    secret: ${AGENT_TS_SECRET}
    name: "agent-ts"
  pos_service:
    secret: ${POS_SERVICE_SECRET}
    name: "pos-service"

POS HMAC Authentication

Per-client HMAC for POS terminal authentication.

Headers Required

X-API-Key-ID: pos_key_abc123
X-Timestamp: 2026-03-10T12:00:00Z
X-Signature: 5d41402abc4b2a76b9719d911017c592

Signature Calculation

func generatePOSSignature(method, path, timestamp string, body []byte, secret string) string {
    payload := strings.Join([]string{method, path, timestamp, string(body)}, "\n")
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write([]byte(payload))
    return hex.EncodeToString(mac.Sum(nil))
}

Client Implementation

// Client-side (JavaScript)
const crypto = require('crypto');

function signPOSRequest(apiKeyId, secret, method, path, rawBody) {
  const timestamp = new Date().toISOString();
  const payload = `${method}\n${path}\n${timestamp}\n${rawBody}`;
  
  const signature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return {
    'X-API-Key-ID': apiKeyId,
    'X-Timestamp': timestamp,
    'X-Signature': signature
  };
}

Partner HMAC Authentication

Partner routes use the same newline-delimited signature format as POS, with one additional header:
X-API-Key-ID: partner_key_abc123
X-Partner-ID: VULT
X-Timestamp: 2026-03-10T12:00:00Z
X-Signature: <hex-hmac>
The canonical string is:
METHOD
PATH
TIMESTAMP
RAW_BODY

Combined Authentication

Some endpoints accept multiple authentication methods using AllowServiceOrUser middleware:
// Accepts either service auth OR user API key/JWT
api.GET("/subscribers/:id", 
    mw.AllowServiceOrUser(),
    h.GetSubscriber,
)

Webhook Authentication

VULT webhooks use HMAC signature verification:

Configuration

webhook:
  vult_hmac_secret: ${VULT_WEBHOOK_SECRET}

Verification Header

X-Webhook-Signature: <hex-hmac-of-raw-body>

Security Best Practices

  • Store keys securely (never in client-side code)
  • Rotate keys periodically
  • Use scopes to limit access
  • Set expiration dates
  • Use strong secrets (minimum 32 characters)
  • Set appropriate expiration times
  • Implement token refresh flows
  • Validate all claims
  • Include timestamp to prevent replay attacks
  • Validate timestamp is within acceptable window (5 min)
  • Use constant-time comparison
  • Rotate secrets periodically

Troubleshooting

  • Verify header format is correct
  • Check API key or JWT is valid and not expired
  • Ensure key has required scopes
  • Check user has required role
  • Verify endpoint is accessible with current auth method
  • Verify secret matches on both sides
  • Check timestamp format: RFC3339 for POS/Partner, unix seconds for service auth
  • Ensure the exact raw body used for signing is what was sent
  • Verify correct encoding (UTF-8)

Next Steps

Configuration

Full config.yaml reference

API Reference

Endpoint documentation