webpack-dev-server: Self-signed TLS certs not valid

  • Operating System: Windows 10 20H2 (19042.685)
  • Node Version: 14.15.1
  • NPM Version: 6.14.8
  • webpack Version: 4.44.2
  • webpack-dev-server Version: 3.11.0
  • Browser: Chrome, Edge, IE
  • This is a bug
  • This is a modification request

Code

Expected Behavior

No warnings in the browser and the app is served on a secure connection.

Actual Behavior

Warning screen with following warning:

NET::ERR_CERT_AUTHORITY_INVALID

By clicking ‘Advanced’ button and then ‘Continue to localhost (unsafe)’ the app loads and works (sort of) for a while. Then same warning screen appears after a while. I would expect there is a way to trust the root CA for this certificate, like any other development webserver? I can’t find any command or documentation how to add a trusted root CA for the automatically created self-signed certificates. Or is the only option to generate our own self-signed certificates? That’s not very helpful or convenient that every developer on the solution has to do that.

For Bugs; How can we reproduce the behavior?

Enable https and start serving the app.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 2
  • Comments: 25 (8 by maintainers)

Most upvoted comments

One convenient way of getting rid of the warning screen is to enable this flag in the browser settings chrome://flags/#allow-insecure-localhost. But the certificate is still invalid and hot-reloading doesn’t work.

I used the Office add-in @creage posted. Worked like a charm and gives you a trusted cert. But I don’t know how to incorporate that into Webpack.

I’ve solved the untrusted cert warning by creating my own root CA (I think I used openssl), adding it to my trusted certs in OS & browsers, then dynamically creating a new client cert signed by my root CA and passing it to webpack-dev-server. It’d be nice if there was an option to point webpack-dev-server at my root CA and have it create the client certs for me, but it’s not hard manually.

In webpack.config.js my config is dynamically built and returned. Here are the pieces you can add to yours to get this to work. This requires the pem module.

Add this somewhere before your config:

const certificates = await getCertificates();

Add this inside your config:

https : {
  key  : certificates.key,
  cert : certificates.cert,
  ca   : certificates.ca,
},

Add this after your config:

function getCertificates() {
  const pem = require('pem');

  const keyFile  = fs.readFileSync(`${__dirname}/../path_to_your_root_ca/ca.key`, 'utf8');
  const certFile = fs.readFileSync(`${__dirname}/../path_to_your_root_ca/ca.crt`, 'utf8');
  const args     = {
    clientKey    : keyFile,
    commonName   : 'localhost',
    organization : 'Your Org',
    locality     : 'Boise',
    state        : 'ID',
    country      : 'US',
  };

  return new Promise((resolve, reject) => {
    pem.createCSR(args, function (error, results) {
      if (error) {
        throw error;
      }

      const args = {
        serviceKey         : keyFile,
        serviceCertificate : certFile,
        csr                : results.csr,
        days               : 30,
      };

      pem.createCertificate(args, function (error, keys) {
        if (error) {
          throw error;
        }

        const data = {
          key  : keys.serviceKey,
          cert : keys.certificate,
          ca   : certFile,
        };

        resolve(data);
      });
    });
  });
}

I guess you are asking if there is a way to create the cert signed by a CA cert to and allow users trust that CA certificate as a one-time operation?

Exactly. That’s how donet/kestrel solves it, you trust a root certificate which is then used by all generated development certificates.

@JohanPetersson did you try with --http2 false?

Unfortunately we are on webpack-dev-server 2.11 and I don’t see this option, but removing h2 from the array here fixed it.