Node.js HTTPS 400 Error - 'UNABLE_TO_VERIFY_LE

2019-04-06 06:15发布

I'm writing a Node.js app that has to request some data from one of our internal APIs. The tricky part is that the server I'm requesting data from has certain limitations:

  • The request must be made on HTTPS protocol (not HTTP)
  • The request must be made using a LAN IP address, because the domain name will not work internally
  • The request must appear to be requesting from the external domain name, because that is what the Virtual Host is setup for.

In order to do this, I'm running a bit of code that looks like this:

var headers = {
    Host: externalHostname,
    Hostname: externalHostname,
};

var options = {
    host: InternalIP,
    path: path,
    method: 'GET',
    headers: headers
};

var req = https.request(options, function(res) {
    res.setEncoding('utf8');

    var data = "";

    res.on('data', function(chunk) {
        data += chunk;
    });

    res.on('end', function() {
        //Do something with that data
    });

    res.on('error', function(err) {
            console.log("Error during HTTP request");
            console.log(err);
    });
});

req.end();

Unfortunately, I'm getting a 400 (Your browser sent a request that this server could not understand) error as a response. I've double and triple checked that the hostname, ip address, and path name are all correct (I can test them from within my browser, and all is good).

I did an output of my response variable (res), and am receiving an authorizationError value of UNABLE_TO_VERIFY_LEAF_SIGNATURE. I'm not sure what that is, or if it's my problem, but it's the only useful bit of information I could find.

I put a full output of my response variable here.

Any ideas on what might be causing this?

Update: I figured it out! I was trying to authenticate with the server by passing a ?PHPSESSID=asdad GET variable, but they have that disabled. I was able to make it work by setting PHPSESSID in the Cookie header.

5条回答
劫难
2楼-- · 2019-04-06 06:46

I hit here while debugging UNABLE_TO_VERIFY_LEAF_SIGNATURE error in an external api call from my nodejs server.

This error is hit when there is error during verification of the server certificate. While it is not recommended to disable the security by the following code (which is also available as another answer), it helps to verify if you are chasing the right bug. In other words, if putting this also does not fix it, there is something else wrong with the code.

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';

In my case, there was silly bug & request was going to localhost itself. Even after putting the above, request failed and that helped me uncover the bug.

Having said that, it is not recommended to use this as a solution. Rather figure out how you can provide additional certificates by setting agent:false & ca:[fs.readFileSync('root-cert.pem')] options. https.request documentation provides details. While chasing my bug, I also found few more useful resources:

  1. ssl-tools.net site provides root & intermediate certificates. For example: Baltimore CyberTrust Root used by lives.api.net
  2. ssl-root-cas module claims to provide additional CA certificates as used by popular browsers. I have not verified the claim.
  3. openssl s_client -connect apis.live.net:443 -- prints the certificate chain. you need to replace the last parameter (url & port) with what you are connecting to.
查看更多
做自己的国王
3楼-- · 2019-04-06 06:51

Try this in command line:

npm config set strict-ssl false

It worked for me on mac.

查看更多
仙女界的扛把子
4楼-- · 2019-04-06 06:59

set this process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';

查看更多
Root(大扎)
5楼-- · 2019-04-06 07:03

check this out from the tls.js source in the latest node.js (there is much more this is what I think you need)

// AUTHENTICATION MODES
//
// There are several levels of authentication that TLS/SSL supports.
// Read more about this in "man SSL_set_verify".
//
// 1. The server sends a certificate to the client but does not request a
// cert from the client. This is common for most HTTPS servers. The browser
// can verify the identity of the server, but the server does not know who
// the client is. Authenticating the client is usually done over HTTP using
// login boxes and cookies and stuff.
//
// 2. The server sends a cert to the client and requests that the client
// also send it a cert. The client knows who the server is and the server is
// requesting the client also identify themselves. There are several
// outcomes:
//
//   A) verifyError returns null meaning the client's certificate is signed
//   by one of the server's CAs. The server know's the client idenity now
//   and the client is authorized.
//
//   B) For some reason the client's certificate is not acceptable -
//   verifyError returns a string indicating the problem. The server can
//   either (i) reject the client or (ii) allow the client to connect as an
//   unauthorized connection.
//
// The mode is controlled by two boolean variables.
//
// requestCert
//   If true the server requests a certificate from client connections. For
//   the common HTTPS case, users will want this to be false, which is what
//   it defaults to.
//
// rejectUnauthorized
//   If true clients whose certificates are invalid for any reason will not
//   be allowed to make connections. If false, they will simply be marked as
//   unauthorized but secure communication will continue. By default this is
//   false.
//

set rejectUnauthorized to false in your options and cross your fingers...let me know if the output changes.

查看更多
SAY GOODBYE
6楼-- · 2019-04-06 07:06

Set this process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; Fixed the UNABLE_TO_VERIFY_LEAF_SIGNATURE problem for superagent.

查看更多
登录 后发表回答