4

I'm having issues using Node.js on Windows to access an HTTPS site running locally in IIS Express, using a self-signed cert. Code to reproduce:

const https = require("https");

const req = https.request(
  {
    hostname: "localhost",
    path: "/api/heroes",
    port: 44323,
    method: "GET"
  },
  res => res.on("data", console.log)
);
req.on("error", console.error);

Running this with node test.js gives:

Error: unable to verify the first certificate
    at TLSSocket.onConnectSecure (_tls_wrap.js:1321:34)
    at TLSSocket.emit (events.js:223:5)
    at TLSSocket._finishInit (_tls_wrap.js:794:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:608:12) {
  code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
}

I can access the page in Chrome without issues; Chrome sees the cert as trusted. I also see the cert in certmgr under Trusted Root Certification Authorities for the current user. I've tried exporting the cert as a PEM, then pointing NODE_EXTRA_CA_CERTS to it; I've also tried creating an https.Agent with its ca property set by reading in the cert. Both give the same error.

Viewing the cert with `openssl x509 -in cert.pem -noout -text gives the following:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            4d:16:7e:86:ce:1a:56:97:48:62:21:cc:7f:ce:ac:55
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=localhost
        Validity
            Not Before: Oct  6 02:20:56 2018 GMT
            Not After : Oct  5 00:00:00 2023 GMT
        Subject: CN=localhost
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:db:6c:55:9e:a5:a8:83:7f:ed:0b:62:88:9c:16:
                    05:31:64:fe:e7:23:73:0a:9e:5e:49:90:c8:ca:98:
                    b5:96:52:ad:36:79:17:81:54:bd:99:99:a1:c3:d3:
                    94:e3:34:83:24:ae:64:e4:33:a7:70:cf:fd:a1:91:
                    df:fb:c4:e5:62:c1:5a:ab:dd:42:e2:b3:33:38:99:
                    9a:be:10:a4:9a:a7:aa:a6:30:59:a6:29:25:3f:95:
                    2f:7e:c8:79:42:8f:d5:54:c1:2b:5e:91:3c:7c:53:
                    e2:34:68:51:21:f2:1a:71:66:78:1c:fc:93:f7:f8:
                    7e:70:43:22:4f:53:8c:5a:9b:08:ef:d4:af:79:b1:
                    be:be:7c:bd:cf:04:9b:30:7f:a7:19:f6:dc:3c:30:
                    b2:6f:83:fd:45:65:1c:2e:66:ad:d6:fc:d6:3d:09:
                    60:53:32:c7:13:24:80:44:25:05:81:41:61:f0:65:
                    32:1a:1b:b2:c7:a0:bb:52:d9:a9:5d:75:4d:d8:ac:
                    6a:d6:e2:97:d8:e0:cc:1b:1e:bf:05:e6:c5:11:69:
                    89:c8:c4:d1:fe:8c:d2:f6:f0:04:bb:38:c7:50:7f:
                    a7:78:80:03:27:a6:86:86:78:d7:5d:d3:cb:47:09:
                    b6:f6:ca:a2:c8:51:95:e2:85:3d:46:74:4f:50:b2:
                    7f:75
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage:
                Digital Signature, Key Encipherment, Data Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 Subject Alternative Name:
                DNS:localhost
    Signature Algorithm: sha256WithRSAEncryption
         45:c4:44:60:e6:bc:a2:8f:8f:db:5e:7c:33:14:a6:59:d7:7e:
         ef:88:e6:75:21:dc:df:3e:3b:be:7c:0e:c7:f4:1e:84:0c:56:
         05:78:41:08:7a:97:f7:47:d9:6f:91:39:b3:9f:0b:b2:e0:c9:
         49:08:3b:9a:80:fd:07:3d:cc:55:21:d2:52:27:f3:a0:f2:35:
         a8:0c:56:0d:4b:c9:20:e1:94:8d:43:b6:f3:72:55:5e:0d:27:
         55:0e:b5:72:26:90:65:fb:28:98:87:bd:c8:68:d5:44:a6:69:
         af:0b:2e:20:e2:4c:7b:50:68:9d:25:56:3c:0d:2d:b9:54:0b:
         21:cf:71:f5:92:ad:b5:72:8f:88:3e:d5:3f:54:40:58:d3:1c:
         40:99:3a:1f:59:40:81:52:39:55:cf:2f:7e:18:27:86:6b:67:
         82:c3:d0:2d:93:91:b3:5b:02:b5:3a:8a:46:90:93:20:ed:09:
         4e:7a:37:f6:21:2b:84:5d:eb:bc:96:63:cd:08:24:4a:0d:ee:
         8a:86:d3:6c:f8:3c:0d:4f:6a:a7:e1:ca:17:83:bb:5e:99:ff:
         87:19:a1:d5:b9:b9:54:59:41:44:32:36:20:bd:3f:4d:ad:6d:
         4f:11:c6:76:77:2d:d7:9e:21:17:eb:d5:fd:a2:58:0a:dc:1d:
         14:5e:d2:f3

I know there are workarounds involving disabling checking certs (or just running the API on plain HTTP locally), but I'm really curious and befuddled why it won't work with HTTPS. Any help is greatly appreciated.

DylanSp
  • 1,379
  • 13
  • 27
  • Check the recipies here: https://stackoverflow.com/questions/45088006/nodejs-error-self-signed-certificate-in-certificate-chain/45088585 – Pak Uula Jun 13 '20 at 07:59
  • @PakUula Those either ignore HTTPS entirely (which I don't want to do, the cert _should_ be trusted) or use the `ca` property, which I've already tried. – DylanSp Jun 13 '20 at 20:37

1 Answers1

0

A self signed certificate is not trusted by definition.

I suggest to use let's encrypt: it's an open source project, completely free, really easy to set up and it let you to avoid wasting time for strange hacks.

It helped me saving a lot of time.

Hope this helps.

Daniele Ricci
  • 15,422
  • 1
  • 27
  • 55
  • I understand that it's not going to be trusted by default, but why wouldn't it work when I use NODE_EXTRA_CA_CERTS or https.agent.ca pointing to the cert? – DylanSp Jun 17 '20 at 13:04
  • The `ca` (also known as intermediate certificate) is the authority certificate and is emitted by the certificate authority. I don't know what you are using as ca certificate, but for a self signed certificate it simply do not exists. If you are the certificate itself as ca cert, your connection results as not trusted because the certificate is not the ca cert. – Daniele Ricci Jun 17 '20 at 13:22