Configure mTLS Authentication with Axios

Mutual TLS (mTLS) provides two-way cryptographic verification between a client and a server to ensure that both parties are authenticated before exchanging data. In this guide, you will learn how to configure mTLS in a Node.js environment using the Axios HTTP client by leveraging Node.js's native https module to pass client certificates, private keys, and certificate authority (CA) bundles.

Prerequisites

To implement mTLS with Axios, you need the following certificate files provided by your server administrator or PKI:

Step-by-Step Configuration

Because Axios runs on top of Node.js's native HTTP/HTTPS modules, mTLS is configured by creating an instance of https.Agent and passing it to Axios via the httpsAgent option.

1. Load Certificate Files

Read the certificates from your file system using Node.js's fs module:

const fs = require('fs');
const path = require('path');

const clientCert = fs.readFileSync(path.resolve(__dirname, 'certs/client.crt'));
const clientKey = fs.readFileSync(path.resolve(__dirname, 'certs/client.key'));
const caCert = fs.readFileSync(path.resolve(__dirname, 'certs/ca.crt'));

2. Create the HTTPS Agent

Instantiate an https.Agent with your credentials:

const https = require('https');

const httpsAgent = new https.Agent({
  cert: clientCert,
  key: clientKey,
  ca: caCert,
  rejectUnauthorized: true // Ensures the server certificate is verified against the provided CA
});

3. Attach the Agent to Axios

You can apply the custom agent to a dedicated Axios instance or to individual requests.

Creating a reusable instance ensures all requests sent through it automatically include the mTLS credentials:

const axios = require('axios');

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  httpsAgent: httpsAgent,
  timeout: 10000
});

async function makeSecureRequest() {
  try {
    const response = await apiClient.get('/secure-data');
    console.log('Response:', response.data);
  } catch (error) {
    console.error('mTLS Request Failed:', error.message);
  }
}

makeSecureRequest();

Using Per-Request Configuration

Alternatively, you can pass the httpsAgent directly inside a single request's configuration object:

axios.get('https://api.example.com/secure-data', { httpsAgent })
  .then(response => console.log(response.data))
  .catch(error => console.error(error));

Additional Configurations

Encrypted Private Keys (Passphrase)

If your client private key is encrypted with a password, provide the passphrase property to the https.Agent:

const httpsAgent = new https.Agent({
  cert: clientCert,
  key: clientKey,
  passphrase: 'your-private-key-password',
  ca: caCert
});

PKCS#12 / PFX Bundles

If your certificate and private key are bundled in a .pfx or .p12 file, use the pfx property instead of cert and key:

const pfxBundle = fs.readFileSync(path.resolve(__dirname, 'certs/bundle.p12'));

const httpsAgent = new https.Agent({
  pfx: pfxBundle,
  passphrase: 'your-bundle-password',
  ca: caCert
});