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-Auth: HMAC timestamp:signature
POS HMACMerchant terminalsX-HMAC-Signature: 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 '{
    "username": "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).

Header Format

X-Service-Auth: HMAC {timestamp}:{signature}

Signature Generation

import crypto from 'crypto';

function generateServiceAuthHeader(
  secret: string,
  timestamp: string,
  body: string
): string {
  const payload = `${timestamp}${body}`;
  const signature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return `HMAC ${timestamp}:${signature}`;
}

// Usage
const timestamp = Math.floor(Date.now() / 1000).toString();
const body = JSON.stringify(requestBody);
const header = generateServiceAuthHeader(
  process.env.AGENT_TS_SECRET,
  timestamp,
  body
);

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-merchant HMAC for POS terminal authentication.

Headers Required

X-Merchant-ID: merchant_abc123
X-Timestamp: 1704067200
X-HMAC-Signature: 5d41402abc4b2a76b9719d911017c592

Signature Calculation

// Server-side verification (Go)
func verifyHMACSignature(
    merchantID string,
    timestamp string,
    body []byte,
    signature string,
) bool {
    secret := getMerchantSecret(merchantID)
    
    payload := fmt.Sprintf("%s%s%s", merchantID, timestamp, body)
    expectedSig := hmac.New(sha256.New, []byte(secret))
    expectedSig.Write([]byte(payload))
    expected := hex.EncodeToString(expectedSig.Sum(nil))
    
    return hmac.Equal([]byte(signature), []byte(expected))
}

Client Implementation

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

function signPOSRequest(merchantID, merchantSecret, body) {
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const payload = merchantID + timestamp + JSON.stringify(body);
  
  const signature = crypto
    .createHmac('sha256', merchantSecret)
    .update(payload)
    .digest('hex');
  
  return {
    'X-Merchant-ID': merchantID,
    'X-Timestamp': timestamp,
    'X-HMAC-Signature': signature
  };
}

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 Headers

X-VULT-Signature: sha256=5d41402abc4b2a76b9719d911017c592...
X-VULT-Timestamp: 1704067200

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 (unix seconds)
  • Ensure body hasn’t been modified
  • Verify correct encoding (UTF-8)

Next Steps