Mutual TLS authentication

The network traffic initiated by Dialogflow for webhook requests is sent on a public network. To ensure that traffic is both secure and trusted in both directions, Dialogflow optionally supports Mutual TLS authentication (mTLS). With mTLS, both the client (Dialogflow) and the server (your webhook server) present a certificate during a TLS handshake, which mutually proves identity.

Requesting mTLS

To request mTLS:

  1. Prepare your webhook HTTPS server to request the client certificate during the TLS handshake.
  2. Your webhook server should verify the client certificate upon receiving it.
  3. Install a root certificate for your webhook server, which can be mutually trusted by both client and server. You should use Google Internet Authority Generation 3 (GIAG3). GIAG3 uses the GlobalSign R2 root, which is owned and controlled by Google Trust Services. You can download it from: https://pki.goog/

Demo Node.js server

The following is a Node.js demo server:

  1. Prepare a self signed certificate and pem file.
  2. Save the following sample as server.js:
    var https = require('https');
    const express = require('express')
    var fs = require('fs');
    var options = {
      // Specify the key file for the server
      key: fs.readFileSync('./server-key.pem'),
      // Specify the certificate file
      cert: fs.readFileSync('./server-crt.pem'),
      // Specify the Certificate Authority certificate
      ca: fs.readFileSync('./ca-crt.pem'),
      // Requesting the client to provide a certificate, to authenticate the user.
      requestCert: true,
      // As specified as "true", so no unauthenticated traffic
      // will make it to the specified route specified
      rejectUnauthorized: false
    };
    
    var app = express();
    app.use(function (req, res, next) {
      if (!req.client.authorized) {
        //return res.status(401).send('Client cert failed. User is not authorized\n');
      }
      // Examine the cert itself, and even validate based on that!
      var cert = req.socket.getPeerCertificate();
      if (cert.subject) {
        console.log('Client Certificate: ',cert);
        console.log('Client Certificate Common Name: '+cert.subject.CN);
        console.log('Client Certificate Location: '+cert.subject.L);
        console.log('Client Certificate Organization Name: '+cert.subject.O);
        console.log('Client Certificate Email Address: '+cert.subject.emailAddress);
      }
    
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end("hello world from client cert\n");
      next();
    });
    var listener = https.createServer(options, app).listen(4433, function () {
      console.log('Express HTTPS server listening on port ' + listener.address().port);
    });
         
  3. Run server.js.
  4. Set requestCert to be true.
    curl https://127.0.0.1:4433 -k
        
  5. Send the client certificate. SSL handshake successfully completes.
    curl -v -s -k --key client-key.pem --cert client-crt.pem https://localhost:4433
    openssl s_client -key client-key.pem -cert client-crt.pem -connect localhost:4433 -CAfile ca-crt.pem
        

Errors

If client certification fails (for example, no client certificate is sent from the client or the client certificate is not signed correctly), the TLS handshake fails and the session terminates.

Common error messages:

Error message Explanation
Failed to verify client's certificate: x509: certificate signed by unknown authority Dialogflow sends its client certificate to the external webhook, but the external webhook cannot verify it. This may be because the external webhook didn't install the root CA correctly. Dialogflow's current CAs are Google Internet Authority Generation 3 (GIAG3) and Tarsier. GIAG3 and Tarsier use the GlobalSign R2 root, which is owned and controlled by Google Trust Services.
Was this page helpful? Let us know how we did:

Send feedback about...

Dialogflow Documentation
Need help? Visit our support page.