I have created a block rule in the Cloudfare WAF using a client certificate in order to have identified requests. Now I need to have this certificate loaded in all requests that passes through my Cloudfare WAF. I know it is difficult to secure the certificate file and key on the frontend browser but I will address this later.
Everything works fine if I load the cert and key on the request either using CURL, python or node.js but if fails when I try to make a request using Axios on react from the Web Browser.
Example with curl(copied from the browser and added the --cert and --key):
curl 'myapi.com' \
--cert cert.crt \
--key cert.key \
-H 'authority: myapi.com' \
-H 'accept: application/json, text/plain, */*' \
-H 'accept-language: en-US,en' \
-H 'origin: http://localhost:3000' \
-H 'referer: http://localhost:3000/' \
-H 'sec-ch-ua: "Not A(Brand";v="99", "Brave";v="121", "Chromium";v="121"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: cross-site' \
-H 'sec-gpc: 1' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36' \
--compressed
Example with node.js:
const crtCertificate = 'cert.crt';
const keyCertificate = 'cert.key';
const fs = require('fs');
const https = require('https');
const httpsAgent = new https.Agent({
cert: fs.readFileSync(crtCertificate),
key: fs.readFileSync(keyCertificate),
});
const options = {
url: apiUrl,
method: 'GET',
httpsAgent: httpsAgent,
};
const fetchData = async () => {
try {
const axiosResponse = await axios(options);
console.log(axiosResponse.data);
} catch (error) {
console.error(error);
}
};
fetchData();
Example with React on the browser(being blocked by the WAF rule):
const options = {
url: url.toString(),
method: init?.method,
headers: {
['Content-Type']: 'application/json',
},
httpsAgent: {
cert: crtCertificate,
key: keyCertificate,
},
data: init?.body,
};
const axiosResponse = await axios(options).then(async (response) => {
return response.data;
});
-> It is important to mention that I also tried passing the certificate chain on the "ca" argument. I used the CA chain from https://curl.se .