60

I have the following code, which is run from a express server:

import fetch from 'node-fetch';

let formBody = [];

const dataLogin = {
      'username': 'myUser',
      'password': 'myPassword'
};

for (let p in dataLogin) {
   let encodedKey = encodeURIComponent(p);
   let encodedValue = encodeURIComponent(dataLogin[p]);
   formBody.push(encodedKey + "=" + encodedValue);
 }

 formBody = formBody.join("&");   

 const url = 'https://external-login-api.com';
 return fetch(url, {
          method: 'POST',
          headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
              'Content-Length': formBody.length         
  },     
  body: formBody
 });

When I run the code I get the following error, despite being able to run the request in Postman with no problems.

{"message":"request to https://external-login-api.com failed, reason: write EPROTO 7316:error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small:openssl\ssl\statem\statem_clnt.c:1472:\n","type":"system","errno":"EPROTO","code":"EPROTO"}

How do I disable SSL verification for this request?

Elliot Blackburn
  • 3,759
  • 1
  • 23
  • 42
Allan Martins
  • 732
  • 1
  • 5
  • 9

2 Answers2

110

The other way to do is to set your own agent to the fetch call.

const fetch = require('node-fetch');
const https = require('https');

const httpsAgent = new https.Agent({
      rejectUnauthorized: false,
    });

const response = await fetch(url, {
      method: 'POST',
      headers: headers,
      body: body,
      agent: httpsAgent,
    });
Karthik
  • 2,282
  • 2
  • 22
  • 23
  • 11
    This is a better approach (if what you want is to Disable SSL verification for node-fetch) since it only limits the ban-lift to the case you need it (like a one off internal query), while still validating the certs of other connections (like third party services) – Manatax Apr 09 '20 at 18:55
  • 2
    I was just running a one-off script against my https localhost server and this was exactly what I needed. Thanks. – n8jadams Dec 06 '21 at 18:37
  • 6
    doesn't work for node18 with build-it fetch – Alex Ivasyuv Jan 24 '23 at 15:17
  • 1
    Works like charm with node 8.x and pm2@2.6.0 for those who are for some reason stuck on node v8.x – Maka Feb 13 '23 at 22:55
84
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

Will ensure you ignore any rejected TLS certificates, or you can set this as an environment variable when running your node service. However this will likely not help, and is probably a bad idea. The SSL error is not because the certificate is invalid (such as a self signed certificate) but instead because of a weak Diffie-Hellman key in the SSL/TLS configuration.

If this a service you're hosting you should look at correcting and improving your TLS/SSL cyphers. See this answer for more information.

The important part is:

You should use 2048-bit Diffie-Hellman groups or larger. You should not be using 512-bit or 1024-bit Diffie-Hellman groups.

If this is a third party service, you should consider contacting them or using a different service as they are leaving themselves open to the Logjam attack which is also discussed in the answer linked above.

Elliot Blackburn
  • 3,759
  • 1
  • 23
  • 42
  • 2
    I'm on a corporate network and almost everything is blocked. This answer saved my life. – Daniel Carpio Contreras Jul 25 '19 at 16:28
  • @DanielCarpioContreras I'm glad I could help :) – Elliot Blackburn Jan 22 '20 at 15:08
  • 1
    Had to set `NODE_TLS_REJECT_UNAUTHORIZED` to zero from powershell before running tests for the flag to take effect. Testing against .Net Core in localhost I was following the [.Net Core instructions to set dev certificates](https://learn.microsoft.com/en-us/dotnet/core/additional-tools/self-signed-certificates-guide#with-dotnet-dev-certs). – user232548 Jan 18 '21 at 20:25
  • @ElliotBlackburn Does the env parameter option work for the built-in `fetch` in Node v18? I tried and it doesn't seem to work. – Old Geezer Mar 01 '23 at 11:11
  • 1
    @OldGeezer I've not really touched nodejs for a few years now but I got curious so went looking. Fetch in node v18 is handled by the undici module which is now being bundled into the nodejs core. It's a full rewrite of http handling as far as I can tell. As a result it doesn't use the old node tls stack and so you need to pass it in separately. The docs for disabling tls verification are here: https://undici.nodejs.org/#/docs/best-practices/client-certificate. – Elliot Blackburn Mar 07 '23 at 22:00
  • @OldGeezer actually, looking into it a bit more that seems to only be about authentication of client provided certificates by a server. I'm unsure how undici handles the reverse (what this question is looking at). I'm afraid I've reached the end of my very rusty nodejs knowledge here. Hopefully that gives you a place to look for more answers though. – Elliot Blackburn Mar 07 '23 at 22:04
  • @OldGeezer Yes, this works for Node v18 built-in fetch. The `rejectUnauthorized` option does not currently work me, possibly because I'm doing a `setGlobalDispatcher()` to a `ProxyAgent` instance (imported `from "undici"`), and it might not support that option. – Allon Guralnek Jun 19 '23 at 02:20