Skip to main content

Security Best Practices

Follow these recommendations to keep your Ruby API integration secure.


Protect Your API Secret

Your team_api_secret is the private key used to generate request signatures. Anyone who holds it can make authenticated API calls on your behalf.

Never expose your team_api_secret in:

  • Client-side JavaScript or mobile app bundles
  • Public Git repositories or version control history
  • Log files, error messages, or analytics events
  • URLs or query parameters

All API calls must originate from your server-side backend, where the secret is not accessible to end users.


Store Secrets Securely

Store credentials outside your source code. Recommended approaches:

EnvironmentRecommended Method
Development.env file (gitignored) loaded via dotenv or equivalent
Staging / ProductionEnvironment variables injected at deploy time
Cloud environmentsSecret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, etc.)

Example — load from environment variable (Python):

import os

API_KEY = os.environ["RUBY_TEAM_API_KEY"]
API_SECRET = os.environ["RUBY_TEAM_API_SECRET"]

Example — load from environment variable (Node.js):

const API_KEY = process.env.RUBY_TEAM_API_KEY;
const API_SECRET = process.env.RUBY_TEAM_API_SECRET;

Key Rotation

Rotate your team_api_key and team_api_secret periodically or immediately if you suspect a compromise.

To request key rotation, contact Ruby support. During rotation:

  1. Ruby issues you a new key pair
  2. Update your environment variables or secret manager with the new values
  3. Redeploy your service to pick up the new credentials
  4. Confirm the old key has been revoked

Keep rotation intervals short for high-security environments (e.g., every 90 days).


Always Use HTTPS

All API requests must be made over HTTPS. Plain HTTP connections are not accepted by the Ruby API server. HTTPS ensures:

  • Request headers (including X-Team-Key and X-Team-Signature) are encrypted in transit
  • The server's TLS certificate can be verified to prevent man-in-the-middle attacks

Ensure your HTTP client validates the server certificate and does not disable TLS verification (e.g., avoid verify=False in Python requests or rejectUnauthorized: false in Node.js).


Clock Synchronization

The X-Team-Timestamp header is validated against server time with a ±300 second tolerance. If your server clock drifts beyond this range, all requests will be rejected with a 401 Unauthorized error.

Synchronize your server clock using NTP (Network Time Protocol):

# Check current time offset (Linux)
timedatectl status

# Force NTP sync (systemd-based systems)
sudo systemctl restart systemd-timesyncd

# Verify NTP is active
timedatectl show --property=NTPSynchronized

For cloud-hosted servers, NTP is typically configured automatically. Verify it is enabled and running.


Use Constant-Time Signature Comparison

If you are implementing Seamless Wallet Callbacks and need to verify incoming signatures from Ruby, always use a constant-time comparison function. Naive string equality (==) is vulnerable to timing attacks that allow an attacker to infer the expected signature byte-by-byte.

Python:

import hmac

def verify_signature(expected: str, received: str) -> bool:
return hmac.compare_digest(expected.encode(), received.encode())

Node.js:

const crypto = require("crypto");

function verifySignature(expected, received) {
const a = Buffer.from(expected, "utf8");
const b = Buffer.from(received, "utf8");
if (a.length !== b.length) return false;
return crypto.timingSafeEqual(a, b);
}

Java:

import java.security.MessageDigest;

public static boolean verifySignature(String expected, String received) {
return MessageDigest.isEqual(
expected.getBytes(StandardCharsets.UTF_8),
received.getBytes(StandardCharsets.UTF_8)
);
}

See Callback Authentication for the full callback signature verification guide.


Summary Checklist

  • team_api_secret is stored server-side only, never in client code
  • Credentials are loaded from environment variables or a secret manager
  • Key rotation is scheduled or can be performed on short notice
  • All API requests use HTTPS with certificate validation enabled
  • Server clock is NTP-synchronized (check periodically)
  • Callback signature verification uses constant-time comparison