Node-fetch: Disable SSL verification - node.js

I have the following code, which is run from a express server:
import fetch from 'node-fetch';
let formBody = [];
const dataLogin = {
'username': 'myUser',
'password': 'myPassword'
};
for (let p in dataLogin) {
let encodedKey = encodeURIComponent(p);
let encodedValue = encodeURIComponent(dataLogin[p]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
const url = 'https://external-login-api.com';
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': formBody.length
},
body: formBody
});
When I run the code I get the following error, despite being able to run the request in Postman with no problems.
{"message":"request to https://external-login-api.com failed, reason: write EPROTO 7316:error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small:openssl\ssl\statem\statem_clnt.c:1472:\n","type":"system","errno":"EPROTO","code":"EPROTO"}
How do I disable SSL verification for this request?

The other way to do is to set your own agent to the fetch call.
const fetch = require('node-fetch');
const https = require('https');
const httpsAgent = new https.Agent({
rejectUnauthorized: false,
});
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: body,
agent: httpsAgent,
});

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
Will ensure you ignore any rejected TLS certificates, or you can set this as an environment variable when running your node service. However this will likely not help, and is probably a bad idea. The SSL error is not because the certificate is invalid (such as a self signed certificate) but instead because of a weak Diffie-Hellman key in the SSL/TLS configuration.
If this a service you're hosting you should look at correcting and improving your TLS/SSL cyphers. See this answer for more information.
The important part is:
You should use 2048-bit Diffie-Hellman groups or larger. You should
not be using 512-bit or 1024-bit Diffie-Hellman groups.
If this is a third party service, you should consider contacting them or using a different service as they are leaving themselves open to the Logjam attack which is also discussed in the answer linked above.

Related

fetchError: unable to verify the self-signed certificate along with net::ERR_CERT_AUTHORITY_INVALID with put method

I am using a next js node server as my app. And a ngnix as my https server with self-signed certificate in which my API node server is at behind.
But I am getting a self-signed certificate error.
So, in my next js , I will contact the https server either by fetch and axios. for example.
Is there a easy way on how to get ride of it without buying SSL from real CA?
What I have tried:
This problem couldn't be by pass thru chrome insecure content enabling since it is a server error.
I am guessing this could be achieved from either setting node server / fetch or axios. But I am so new on this kind of problem.
second update
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
works to get rid of the fetch error:
But now it shown this error with put method:
net::ERR_CERT_AUTHORITY_INVALID
What I have done is to put process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; on every api call.
For example
try {
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
const res = await axios.put(url);
} catch (error) {
console.log(error);
}
I am still looking for a solution.
Try adding httpsAgent in your fetch call
const https = require('https');
const httpsAgent = new https.Agent({
rejectUnauthorized: false,
});
const response = await fetch("https://localhost/api", {
// Adding method type
method: "POST",
// Adding body or contents to send
body: JSON.stringify(
{data:"data"}),
// Adding headers to the request
headers: {
"Content-type": "application/json; charset=UTF-8"
},
agent: httpsAgent,
})
It worked for me

Nodejs Axios Error: Hostname/IP doesn't match certificate's altnames: "Host: (URL). is not in the cert's altnames: DNS:*.sa-east-1.es.amazonaws.com"

I'm trying to request an API from a third party server from a shared hosting server, so i don't have root access, and receive this error, but when i try it from my insomnia, it works normally, aparently its something due to proxy or certificates. Already tried using httpsAgent: new https.Agent({ rejectUnauthorized: false }) in axios request options, and tried NODE_TLS_REJECT_UNAUTHORIZED=0, but no success. I didn't paste cert and server info info but if it's necessary i can share it. That's how i'm making the request:
async appInfo(){
var config = {
method: 'get',
url: `${this.url}/api/v2/me/shipment/app-settings`,
headers: {
'Accept': 'application/json',
'Authorization':`Bearer ${this.bearer}`,
'User-Agent': this.user_agent
}
};
var response = await axios(config)
console.log(JSON.stringify(response.data));
}
i don't know if you fixed it already, but i will answer anyways. It might help others. Here's the solution i found here: https://github.com/axios/axios/issues/1650
Seeing your code, you should have the agent config outside of the header. Like that:
// At instance level
const instance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
});
instance.get('https://something.com/foo');
// At request level
const agent = new https.Agent({
rejectUnauthorized: false
});
axios.get('https://something.com/foo', { httpsAgent: agent });
Warning: It may be a security failure, only use it if you really trust where you sharing the data.
Cheers.

Nodejs https.request and axios

I am having a very weird issue by using the Nodejs https module.
What I was trying to do is, calling the 3rd party API for some service, the following is my code:
const https = require("https");
function request(accessId, secretKey, host, api, body, timeout=3000) {
let bodyString = JSON.stringify(body);
let time = Math.round(new Date().getTime()/1000).toString();
// I have implemented the signBody function
let sign = signBody(accessId, secretKey, time, bodyString);
let header = {
"Content-Type": "application/json",
"AccessId": accessId,
"TimeStamp": time,
"Sign": sign,
};
let options = {
method: 'POST',
timeout: timeout,
headers: header,
}
let url = new URL(api,host);
https.request(url, options, (res) => {...});
}
They weird part is, if I'm running the function by node xxx.js to trigger the request("MY_ACCESS_ID", "MY_SECRET_KEY", "https://api.xxxx.com", "/service/api/v3", MY_BODY) function, it works as expected. However, this request(...) function is part of my webserver, and it is used by a API (I'm using express.js), such as:
// the myService implemented the request() function
let myService = require("./myService.js")
router.get("/myAPI", (req, res, next) => {
request("MY_ACCESS_ID", "MY_SECRET_KEY", "https://api.xxxx.com", "/service/api/v3", MY_BODY)
})
it always shows the error: Error: connect ECONNREFUSED 127.0.0.1:443
I have no idea why the same code is behaving different. I thought it probably https.request issue. they I tried to use axios for the post request. The other weird things showed up. By using the exactly same header, https.request() returns success from the service provider and axios.post returns error message: Sign check error, please check the way to generate Sign.
This is so crazy....no idea of this issue. Any idea ??
BTW, I have solved the issue by implementing as:
const https = require("https");
function request(accessId, secretKey, host, api, body, timeout=3000) {
let bodyString = JSON.stringify(body);
let time = Math.round(new Date().getTime()/1000).toString();
// I have implemented the signBody function
let sign = signBody(accessId, secretKey, time, bodyString);
let header = {
"Content-Type": "application/json",
"AccessId": accessId,
"TimeStamp": time,
"Sign": sign,
};
let options = {
hostname: host,
path: api,
method: 'POST',
timeout: timeout,
headers: header,
}
https.request(options, (res) => {...});
}
But still no idea what is the difference.
I would check the final url constructed inside the https.request method. The non-working version makes a request to 127.0.0.1:443, which wouldn't work since your localhost doesn't support https(only http) and 443 is usually for https.
See https://nodejs.org/api/https.html#https_https_request_url_options_callback for default port number.
Axios has different implementation inside the post() method and it may manipulate your sign string by url encoding it before sending to the 3rd-party API.

HTTP request with SSL 128 bits

Working on a webapp using Ogone Direct Paiment, a code working for an old account is working but giving me same error for the new one.
I've added the call made and the answer, maybe someone is used to Ogone API.
The error seems to tell me I have to make a SSL 128bit call but I have no idea how to do that. I've tried lot of things, including userAgent, generate certificate myself with openssl command but without result.
If you're familiar with Ogone, let me know how to fix it or how to change the configuration to allow simple queries.
Otherwise, could you explain me how to make a SSL 128 bit call with nodeJS module request?
Request call
const request= require('request');
const datas = {
url : 'https://secure.ogone.com/ncol/prod/orderdirect_utf8.asp',
method:"POST",
form: 'queryUrlEncoded',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
request(datas, (err, response, body) => {
err && console.error(err);
body && console.log(body);
});
Response received
<?xml version="1.0"?>
<ncresponse [...] NCSTATUS="5" NCERROR="50001115" NCERRORPLUS="SSL 128 required">
</ncresponse>
The module you are using has feature to apply SSL but for that you would need a certificate with key, long story short, yes it is possible.
const fs = require('fs')
, path = require('path')
, certFile = path.resolve(__dirname, 'ssl/client.crt')
, keyFile = path.resolve(__dirname, 'ssl/client.key')
, caFile = path.resolve(__dirname, 'ssl/ca.cert.pem')
, request = require('request');
const options = {
url: 'https://api.some-server.com/',
cert: fs.readFileSync(certFile),
key: fs.readFileSync(keyFile),
passphrase: 'password',
ca: fs.readFileSync(caFile)
};
request.get(options);
Copied from documentation.
Click Here for Documentation

How to fix 'Hostname/IP does not match certificate's altnames'

I have a problem when I run get a response for service. There are two services. For the first service, it's working perfectly but in the second I have issue "Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Cert is empty". When I used Postman with certificates its works perfectly. What should I set or implement to make it works?​
I tried using: checkServerIdentity, rejectUnauthorized: true.
let options = {
hostname: 'ws.aaa.bbb.nn',
path: '/api',
method: 'GET',
key: fs.readFileSync('/private.crt'),
cert: fs.readFileSync('/public.crt'),
passphrase: '***'
};
const req = https.request(options, (res) => {
let body = '';
res.on('data', (chunk)=> {
body += chunk;
console.log(body)
});
});
Should be status code 200.
Seems you got a bad certificate.
Get a correct one or just turn the SSL certificate verification off.
I had the same problem, Just try to set Authorization Type to "Inherit auth from parent".

Resources