Node.js HTTPS 400 Error - 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'

15,436

Solution 1

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

Solution 2

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.
Share:
15,436
jwegner
Author by

jwegner

merge me

Updated on July 19, 2022

Comments

  • jwegner
    jwegner almost 2 years

    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.

  • Mike L.
    Mike L. about 12 years
    devel.dyne.org/jmx/tree/jsapi/node/… here is the source, look around line 755
  • jwegner
    jwegner about 12 years
    I think you may have my situation a little backwards. This (I believe) is if I'm creating an SSL server - the verbage in that document seems to suggest that requestCert and rejectUnauthorized are set on the server. I, however, am trying to make a HTTPS request from a different (apache) server.
  • Mike L.
    Mike L. about 12 years
    If that is the case, then UNABLE_TO_VERIFY_LEAF_SIGNATURE is something that your server is returning to you, that error has nothing to do with node.js
  • ThomasReggi
    ThomasReggi over 10 years
    @MikeL. This is bull. I right now have a simple request function to an external API and I'm getting UNABLE_TO_VERIFY_LEAF_SIGNATURE and in Postman the same headers are being applied and it is working perfectly. Why is that? How can you tell me it has nothing to do with node?
  • Ron
    Ron over 10 years
    thanks! this fixed my issue with node.js and zombie and being able to watch the HTTPs traffic in fiddler ( as well as having to set the zombie browser option to the fiddler proxy )
  • docwhat
    docwhat almost 10 years
    This is a lousy idea. If the system has the proper CA root (AKA anchor) certificates, there should be a way to tell Node about them instead of turning off strict-ssl.
  • docwhat
    docwhat almost 10 years
    This is a lousy idea. If the system has the proper CA root (AKA anchor) certificates, there should be a way to tell Node about them instead of turning off strict-ssl.