wwwuser
wwwuser

Reputation: 6352

Node.js request CERT_HAS_EXPIRED

I'm using Mikeal's request (https://github.com/mikeal/request) to make an https request to a server. However, I keep getting an authorization error of CERT_HAS_EXPIRED.

request({
        url: 'https://www.domain.com/api/endpoint',
        strictSSL: false
    }, function(error, response, body) {
        if(!error && response.statusCode == 200) {
            res.json(JSON.parse(body));
        } else {
           res.json(response.statusCode, {'error': 'error'})
        }
});

I've tried setting strictSSL to true and false, both output same error of CERT_HAS_EXPIRED. What is causing this issue and is there any way to fix it in nodejs?

Upvotes: 91

Views: 228708

Answers (8)

Bekir İnan
Bekir İnan

Reputation: 13

You can do all your Slack requests with a custom slack SSL certificate. You need to download the slack SSL .pem file from the Slack website.

const { request, token, variables } = props;
//Slack certificate adding to request.
//Don't remove this part required for slack request
const certPath = `${auth.slack.certificatePath}/slack-ssl-certificate-2023-03-17.pem`;
const sslCert = fs.readFileSync(certPath);
const agent = new https.Agent({
  ca: sslCert,
  rejectUnauthorized: true
});

const client = new WebClient(token, {
  agent
});

const result = await client.apiCall(request, {
  ...variables,
});

return {
  status: 200,
  result,
  error: '',
};

Upvotes: 0

factorypolaris
factorypolaris

Reputation: 2847

Updating Nodejs will force request's cache to be flushed.

This worked for me when nothing else did.

Upvotes: 1

Max
Max

Reputation: 999

If someone is having this issue today while using an old version of nodejs, this might be due to Lets's encrypt 30th sept. 2021 ROOT CA expiry already mentionned in this answer.

certificates are hardcoded in node source code and the new ISRG Root X1 certificate was only added in this commit.

One can either update their node version, use node --use-openssl-ca flag (assuming openssl certificates are up to date), use the http agent solution mentionned in other answers (I didn't test it), or set process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0 as a quick and dirty workaround.

Upvotes: 72

NTyler
NTyler

Reputation: 1427

Here is a more concise way to achieve the "less insecure" method proposed by CoolAJ86

request({
  url: url,
  agentOptions: {
    rejectUnauthorized: false
  }
}, function (err, resp, body) {
  // ...
});

Upvotes: 38

coolaj86
coolaj86

Reputation: 77004

The best way to fix this:

Renew the certificate. This can be done for free using Greenlock which issues certificates via Let's Encrypt™ v2

A less insecure way to fix this:

'use strict';

var request = require('request');
var agentOptions;
var agent;

agentOptions = {
  host: 'www.example.com'
, port: '443'
, path: '/'
, rejectUnauthorized: false
};

agent = new https.Agent(agentOptions);

request({
  url: "https://www.example.com/api/endpoint"
, method: 'GET'
, agent: agent
}, function (err, resp, body) {
  // ...
});

By using an agent with rejectUnauthorized you at least limit the security vulnerability to the requests that deal with that one site instead of making your entire node process completely, utterly insecure.

Other Options

If you were using a self-signed cert you would add this option:

agentOptions.ca = [ selfSignedRootCaPemCrtBuffer ];

For trusted-peer connections you would also add these 2 options:

agentOptions.key = clientPemKeyBuffer;
agentOptions.cert = clientPemCrtSignedBySelfSignedRootCaBuffer;

Bad Idea

It's unfortunate that process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; is even documented. It should only be used for debugging and should never make it into in sort of code that runs in the wild. Almost every library that runs atop https has a way of passing agent options through. Those that don't should be fixed.

Upvotes: 161

conny
conny

Reputation: 10145

I think the strictSSL: false should (should have worked, even in 2013) work. So in short are three possible ways:

  1. (obvious) Get your CA to renew the certificate, and put it on your server!
  2. Change the default settings of your request object:

    const myRequest = require('request').defaults({strictSSL: false})

    Many modules that use node-request internally also allow a request-object to be injected, so you can make them use your modified instance.
  3. (not recommended) Override all certificate checks for all HTTP(S) agent connections by setting the environment variable NODE_TLS_REJECT_UNAUTHORIZED=0 for the Node.js process.

Upvotes: 15

Dan Kohn
Dan Kohn

Reputation: 34327

Add this at the top of your file:

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

DANGEROUS This disables HTTPS / SSL / TLS checking across your entire node.js environment. Please see the solution using an https agent below.

Upvotes: 93

Angular University
Angular University

Reputation: 43087

Try to temporarily modify request.js and harcode everywhere rejectUnauthorized = true, but it would be better to get the certificate extended as a long-term solution.

Upvotes: 0

Related Questions