Add Cryptographic Timestamps in Axios Interceptors

This article demonstrates how to automatically intercept outgoing HTTP requests in Axios to generate and attach cryptographic timestamps. By leveraging Axios request interceptors alongside standard cryptographic hashing algorithms, you can secure API communications against replay attacks and guarantee payload integrity before any data leaves the client.

Understanding Axios Request Interceptors

Axios provides interceptors that allow you to modify requests before they are sent over the network. By attaching a request interceptor, you can dynamically read the request payload, generate a precise timestamp, compute a cryptographic signature using a shared secret, and inject both values into custom HTTP headers.

Implementation Example

The following example uses Node.js's built-in crypto module (or an equivalent library like crypto-js for browser environments) along with Axios to sign requests using HMAC-SHA256.

const axios = require('axios');
const crypto = require('crypto');

// Secret key shared between client and server
const API_SECRET = 'your-secure-shared-secret';

// Create a custom Axios instance
const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000,
});

// Register the request interceptor
apiClient.interceptors.request.use(
  (config) => {
    // 1. Generate an ISO 8601 or UNIX millisecond timestamp
    const timestamp = Date.now().toString();

    // 2. Normalize the request method and body/params for signing
    const method = config.method ? config.method.toUpperCase() : 'GET';
    const payload = config.data ? JSON.stringify(config.data) : '';
    const urlPath = config.url || '';

    // 3. Create the canonical string to sign
    const signaturePayload = `${timestamp}:${method}:${urlPath}:${payload}`;

    // 4. Generate the cryptographic signature (HMAC-SHA256)
    const signature = crypto
      .createHmac('sha256', API_SECRET)
      .update(signaturePayload)
      .digest('hex');

    // 5. Append headers to the outgoing request
    config.headers['X-Timestamp'] = timestamp;
    config.headers['X-Signature'] = signature;

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// Example usage
async function sendData() {
  try {
    const response = await apiClient.post('/v1/transactions', {
      account: '12345',
      amount: 100.0,
    });
    console.log('Response:', response.data);
  } catch (error) {
    console.error('Request failed:', error.message);
  }
}

sendData();

How It Works

  1. Timestamp Generation: The interceptor captures the exact time the request is dispatched via Date.now().
  2. Canonical String Construction: The HTTP method, request path, timestamp, and request body are concatenated into a predictable string structure.
  3. Cryptographic Hashing: The canonical string is signed using HMAC-SHA256 with a pre-shared secret key, generating a deterministic digest.
  4. Header Injection: The interceptor appends X-Timestamp and X-Signature to the request's headers object, passing the modified configuration down the Axios execution pipeline.

Server-Side Verification Rules

To complete the security implementation, the receiving server must validate the incoming headers: