184

I am facing a problem with client side https requests.

A snippet can look like this:

var fs = require('fs');
var https = require('https');

var options = {
    hostname: 'someHostName.com',
    port: 443,
    path: '/path',
    method: 'GET',
    key: fs.readFileSync('key.key'),
    cert: fs.readFileSync('certificate.crt')
}

var requestGet = https.request(options, function(res){
    console.log('resObj', res);
}

What I get is Error: self signed certificate in certificate chain.

When I use Postman I can import the client certificate and key and use it without any problem. Is there any solution available?? I would also like to be given some lights on how postman handles the certificates and works.

12 Answers 12

274

Option 1: Disable the warning (useful for dev)

From your question I'm guessing you are doing this in development as you are using a self signed certificate for SSL communication.

If that's the case, add as an environment variable wherever you are running node

export NODE_TLS_REJECT_UNAUTHORIZED='0'
node app.js

or running node directly with

NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js

This instructs Node to allow untrusted certificates (untrusted = not verified by a certificate authority)

If you don't want to set an environment variable or need to do this for multiple applications npm has a strict-ssl config you set to false

npm config set strict-ssl=false

Option 2: Load in CA cert, like postman (useful for testing with TLS)

If you have a CA cert already like the poster @kDoyle mentioned then you can configure in each request (thanks @nic ferrier).

 let opts = {
    method: 'GET',
    hostname: "localhost",
    port: listener.address().port,
    path: '/',
    ca: fs.readFileSync("cacert.pem")
  };

  https.request(opts, (response) => { }).end();

Option 3: Use a proper SSL Cert from a trusted source (useful for production)

letsencrypt.org is free, easy to set up and the keys can be automatically rotated. https://letsencrypt.org/docs/

Sign up to request clarification or add additional context in comments.

13 Comments

If I understand you correctly, setting that env_var in server will only disable the process of verification, which is something I don't want to do. I need to only do what postman does i.e. to import somehow the certificate.
is the value you gave here: cert: fs.readFileSync('certificate.crt') the absolute location of the cert?
I can't believe I finally found something to stop this error. I f'ing tried everything. worked on Jan.31.19,
Which is better: above NODE_TLS_REJECT_UNAUTHORIZED=0 env variable or below "npm config set strict-ssl=false" solution. Just curious whats more kosher.
@armyofda12mnkeys I think it depends on your setup. It's easier to add the Environment variable to the source code either as a developer only npm script or when running a docker container so others using your project don't run into the same issue. Setting the npm config is probably better if you aren't in a team or just coding for fun as then you don't need to keep setting it everywhere, you only have to do it once
|
65

You can fix this issue using NODE_TLS_REJECT_UNAUTHORIZED=0 in the terminal or inserting the following line within the JS file.

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;

Beware that this a hack and it should not be used in production.

If you are using windows then run the following command in the command prompt:

set NODE_TLS_REJECT_UNAUTHORIZED=0 

After that, npm install <my-package> will work.

5 Comments

Should be process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
This worked (number), didn't do the string version, I am running node.js on windows.
both works, First one (number) worked for me. (centos)
I am getting error while using SelfSigned cert for ftp on windows and using ftp npm module. Is the solution different for it ?
What would be the equivalent command on MAC?
22

for Nodemailer:

adding

tls: {
  rejectUnauthorized: false
}

solved my problem.

Overall code looks liek this:

nodemailer.createTransport({
    host: process.env.MAIL_SERVER,
    secure: false,
    port: 587,
    auth: {
      user: process.env.MAIL_USERNAME,
      pass: process.env.MAIL_PASSWORD
    },
    tls: {
      rejectUnauthorized: false
    }
  }

2 Comments

this is a horrible solution. it disables security and absolutely includes transmission of a username and password.
This answer results in a security issue, because validation of X.509 certificates is essential to create secure SSL/TLS sessions not vulnerable to man-in-the-middle attacks. See MITRE, CWE-295 for more information.
17

You can write command npm config set strict-ssl false

Comments

16

you just add at the start of your code this line:

process.env.NODE_TLS_REJECT_UNAUTHORIZED='0'

And everything solved, but in any case it is not recommendable, I am investigating the solution of https://letsencrypt.org/

1 Comment

It works, but I think its a temporary solution only for our app up and running . It gives the following warning Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
12

Turning off verification is quite a dangerous thing to do. Much better to verify the certificate.

You can pull the Certificate Authority certificate into the request with the ca key of the options object, like this:

let opts = {
    method: 'GET',
    hostname: "localhost",
    port: listener.address().port,
    path: '/',
    ca: await fs.promises.readFile("cacert.pem")
  };

https.request(opts, (response) => { }).end();

I put a whole demo together of this so you can see how to construct SSL tests.

It's here.

Comments

10

The node application needs to have the CA certificate added to the existing CA (Mozilla) certificates.

We start node using a service, and add the environment variable, NODE_EXTRA_CA_CERTS

[Service]
Restart=always
User=<...>
Group=<...>
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
Environment=NODE_EXTRA_CA_CERTS=/<...>/.ssl/extra_certs.pem
WorkingDirectory=/<...>

ExecStart=/usr/bin/node -r dotenv/config /<.....>/server.js dotenv_config_path=/<....>/.env

This way we can use the same application to call services using popular CAs or our own self signed certs, and we don't have to turn off SSL checking.

In linux there is an easy way to get the certificate, use this post: Use self signed certificate with cURL?

You create your certificate using:

$ echo quit | openssl s_client -showcerts -servername server -connect server:443 > cacert.pem

then copy that .pem file as the extra_cert.pem. You can only have one pem file, but you can append multiple pem files into one file.

I hope this helps someone, it took me a while to find the different parts to make this work.

3 Comments

This is the best option and does not compromise on security!
Using dotenv for this does not work: github.com/nodejs/node/issues/20432
I'm with @st.huber this is the best and most secure solution, but it's hidden in the answer. Set the NODE_EXTRA_CA_CERTS environment variable to the path of the correct root certificate
8

Do:

Better use this if running a node script for standalone purpose,

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;

Don't:

instead of changing all default request process.

npm config set strict-ssl=false

i.e., don't alter your node config, else it will apply to all your requests, by making it default config. So just use it where necessary.

2 Comments

your "do" and "dont" have equal consequences.... the env var is going to override the npm config anyway, both expose you to man in the middle attacks.
yes, but one applies to the current project and other to all projects. so, you would know what you are doing knowingly and what unknowingly.
2

For what it's worth, after spending a day and a half trying to track this one down it turned out the error was caused by a setting on my company's firewall that IT had to disable. Nothing anywhere on the internet did anything to fix this.

1 Comment

What was the thing that your IT had to disable?
1

When you are doing Setup Sitecore Headless SXA with Next js and you got Error: self-signed certificate

This commend will work for you

$env:NODE_TLS_REJECT_UNAUTHORIZED=0

Comments

0

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; Even though its not worked ...

Not Able to Install Cypress:

S C:\Cypress> export NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js export : The term 'export' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again. At line:1 char:1

  • export NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js
  •   + CategoryInfo          : ObjectNotFound: (export:String) [], CommandNotFoundException   
      + FullyQualifiedErrorId : CommandNotFoundException
    
    

2 Comments

presumably because that's not how you set/export environment variables in powershell.
@starball is correct. to set the env var in powershell you'd use $env:NODE_TLS_REJECT_UNAUTHORIZED instead of export NODE_TLS_REJECT_UNAUTHORIZED, but both are bad directions because of the MITM attack exposure.
0

I had this error recently and you DON'T HAVE TO DISABLE SSL.

The right way to fix it is to add the certificate path to the ENV variable `NODE_EXTRA_CA_CERTS`.

This way, Node'll use it and boom, problem solved ;)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.