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:
- Client Certificate (
client.crt): The public certificate identifying the client. - Client Private Key (
client.key): The private key associated with the client certificate. - CA Certificate (
ca.crt- Optional): The root or intermediate Certificate Authority certificate used to verify the server's identity.
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.
Method A: Using a Custom Axios Instance (Recommended)
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
UNABLE_TO_VERIFY_LEAF_SIGNATUREorSELF_SIGNED_CERT_IN_CHAIN: The server's certificate chain cannot be verified. Ensure the correctcacertificate is supplied in thehttpsAgent.ERR_OSSL_PEM_NO_START_LINE: The certificate or key format is invalid. Ensure files are correctly encoded in standard PEM format (beginning with-----BEGIN CERTIFICATE-----or-----BEGIN RSA PRIVATE KEY-----).- File Paths: Use absolute paths (e.g., via
path.resolve(__dirname, 'cert.pem')) to avoid runtime resolution errors if the application is executed from different working directories.