Configure mTLS with Custom Certificates in Axios

Mutual TLS (mTLS) ensures two-way cryptographic authentication between a client and a server, requiring the client to prove its identity using a certificate. In a Node.js environment, configuring mTLS with custom certificates and private keys in Axios is achieved by leveraging Node's native https module to create a custom https.Agent that is passed directly into the Axios configuration.

Prerequisites

To configure mTLS, ensure you have the following certificate files available in PEM format:

Note: mTLS programmatic configuration in Axios only works in the Node.js runtime. Web browsers handle TLS certificates at the operating system or browser level.

Step-by-Step Configuration

1. Import Required Modules

You will need the fs module to read your certificate files from disk, the https module to configure the TLS agent, and axios.

2. Initialize the HTTPS Agent

Create an instance of https.Agent containing your custom certificates:

const fs = require('fs');
const https = require('https');
const axios = require('axios');

// Load certificate and key files
const httpsAgent = new https.Agent({
  cert: fs.readFileSync('./certs/client.crt'),
  key: fs.readFileSync('./certs/client.key'),
  ca: fs.readFileSync('./certs/ca.crt'), // Optional: Provide if using a private or self-signed CA
  rejectUnauthorized: true               // Ensures server certificate validity is enforced
});

3. Attach the Agent to Axios

You can apply the httpsAgent globally by creating a custom Axios instance or attach it to individual requests.

Creating a reusable instance automatically applies mTLS to all requests made with that client:

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  httpsAgent: httpsAgent,
  headers: {
    'Content-Type': 'application/json'
  }
});

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

sendRequest();

Method B: Per-Request Configuration

Pass the agent directly into the Axios request options:

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

Handling Encrypted Private Keys

If your private key is protected by a passphrase, provide the passphrase property inside the https.Agent configuration:

const httpsAgent = new https.Agent({
  cert: fs.readFileSync('./certs/client.crt'),
  key: fs.readFileSync('./certs/client.key'),
  passphrase: 'your-secure-passphrase',
  ca: fs.readFileSync('./certs/ca.crt')
});

Troubleshooting Common Issues