Mutual TLS: Stuff you should know
Mutual TLS enables the server to authenticate the identity of the client.
- Authentication isn’t enough: Client access control
- An alternative: Digitally signing the message
- The TLS handshake protocol
- TLS: Authenticating the server
- Mutual TLS: Authenticating the client
- Configuring Mutual TLS on the client (Docusign)
- Configuring Mutual TLS on the server (your application)
- Mutual TLS for the Apache2 web server
- Configuring client access control
- Debugging Mutual TLS on the Apache web server
- Frequently asked questions
- Summary
- Additional resources
- Updates
Table of contents
- Authentication isn’t enough: Client access control
- An alternative: Digitally signing the message
- The TLS handshake protocol
- TLS: Authenticating the server
- Mutual TLS: Authenticating the client
- Configuring Mutual TLS on the client (Docusign)
- Configuring Mutual TLS on the server (your application)
- Mutual TLS for the Apache2 web server
- Configuring client access control
- Debugging Mutual TLS on the Apache web server
- Frequently asked questions
- Summary
- Additional resources
- Updates
Any time you use a web browser to connect to a secure site (https://something), you’re using Transport Layer Security (TLS). TLS is the successor to SSL and it’s an excellent standard with many features. TLS guarantees the identity of the server to the client and provides a two-way encrypted channel between the server and client.
But for a webhook application such as Docusign Connect, that’s not enough since your application is the server and you want to confirm the identity of the client, Docusign. What’s the solution?
Mutual TLS to the rescue! It’s an optional feature for TLS. It enables the server to authenticate the identity of the client.
Authentication isn’t enough: Client access control
But authenticating the client (knowing who it is), is not enough. To be secure, your listener app must also use access control to ensure that only Docusign can access your listener app.
An alternative: Digitally signing the message
Mutual TLS plus Client Access Control enables your listener app to ensure that the Connect notification message was sent by Docusign and that it wasn’t modified en route.
The Connect HMAC option is recommended over Mutual TLS since it guarantees both that the message was sent by Docusign and provides an end-to-end message integrity check.
The Connect Basic Authentication option can be easily set up and is recommended to be used along with the HMAC feature.
The TLS handshake protocol
When you connect to https://whatever/, the TLS handshake protocol is used to negotiate and set up a secure, encrypted channel between the client and the server. The handshake protocol consists of a series of required and optional messages sent between the server and the client.
The handshake protocol and its messages are described in the TLS 1.2 standard itself. An article by Álvaro Castro-Castilla is also useful for understanding the protocol.
TLS: Authenticating the server
The server sends its digital X.509 certificate (and any intermediate certificates) to the client. The client verifies the server’s certificate by using one of its pre-trusted root certificates. Most clients use the Microsoft or Mozilla set of trusted root certificates. At the end of this process, the client knows exactly who the server is. When you’re browsing the web, the result of this process is the green lock symbol indicating that your browser has established a trust relationship with the server.
Mutual TLS: Authenticating the client
The TLS handshake Certificate Request message is optionally sent by the server to the client. The Certificate Request message includes a list of Distinguished Names of root certificates that the server trusts. It tells the client (Docusign in our case) to respond with its own certificate or with its certificate and any needed intermediate certificates.
The client responds with a Client Certificate message. It includes the client’s certificate (and needed intermediate certificates) that chain to one of the Distinguished Names listed in the Certificate Request message.
After sending the Certificate Request message and receiving a reply, the server verifies the client’s certificate. When verification is successful, the server has authenticated the client.
Configuring Mutual TLS on the client (Docusign)
To enable Mutual TLS, check the Enable Mutual TLS option in the Docusign Admin tool for your Connect configuration. If you’re programmatically creating the Connect configuration, set the signMessageWithX509Certificate field to “true”.
If you’re using the eventNotification settings in the Envelopes: create method, set the signMessageWithX509Cert field to “true”. It is not necessary to use the Admin tool’s “Require Mutual TLS” setting and setting only that field is not sufficient.
Configuring Mutual TLS on the server (your application)
Your Connect webhook application’s listener either includes a web server or is a client of a web server, depending on your application’s development stack. Mutual TLS must be enabled and configured on the system that negotiates the TLS connection with the Docusign client.
Mutual TLS for the Apache2 web server
Step 1: Obtain the root certificate for the client
During the mutual TLS part of the handshake, the server (your listener), sends the client (Docusign) the root Distinguished Name that the server trusts. The client then responds with a matching certificate/intermediate certificate bundle.
The Docusign Trust site’s certificates page includes a link to the Connect root cert. It has common name DigiCert Global Root G2. The same certificate is available from the DigiCert web site. It is a 2048 bit certificate. Some older software versions may not be able to use a 2048 bit certificate and will need to be upgraded.
Copy the certificate, including the “BEGIN/END CERTIFICATE” lines to a file on your webserver. Use the name docusign_root_cert.pem or similar for the certificate file.
Step 2: Configure your web server
The following information is for the apache 2.4 web server. Different but similar instructions apply for IIS, F5, nginx and other web servers.
These apache 2.4 directives require the client to support mutual TLS. They can be applied to specific directories, or to all incoming connections. See the Apache2.4 SSL documentation.
SSLVerifyClient require
SSLVerifyDepth 10
SSLCACertificateFile /etc/apache2/conf/docusign_root_cert.pem
Configuring client access control
Your web server is now using Mutual TLS to require that the client (Docusign) provide its X.509 certificate to identify itself. The next step is to use the client’s identity for access control. This example for apache 2.4 is applied to a specific directory.
First the SSL library is set to create environment variables with information from the client’s certificate. Next, the client’s CN (common name) is checked to ensure that it’s either the demo Docusign system or one of the production systems.
<directory>
SSLOptions +StdEnvVars
<requireany>
Require expr %{SSL_CLIENT_S_DN_CN} == "demo.connect.docusign.net"
Require expr %{SSL_CLIENT_S_DN_CN} == "connect.docusign.net"
Require expr %{SSL_CLIENT_S_DN_CN} == "eu.connect.docusign.net"
</requireany></directory>
Debugging Mutual TLS on the Apache web server
For Apache 2.4, use the following to debug SSL:
<ifmodule mod_ssl.c>
ErrorLog /var/log/apache2/ssl_engine.log
LogLevel ssl:debug
# LogLevel ssl:trace8
</ifmodule>
The debug SSL log level provides helpful information in the server’s general error log. The debug messages tell you that the mutual TLS certificate request worked and the identity of the client (Docusign):
ssl_engine_kernel.c(1560): [client 162.248.184.11:25063]
AH02275: Certificate Verification, depth 0, CRL checking mode: none
[subject: CN=connect.docusign.net,OU=Technical Operations,
O=Docusign\\, Inc.,L=Seattle,ST=Washington,C=US /
issuer: CN=Symantec …
The following SSL debug message means that the mutual TLS certificate request didn’t work:
SSL Library Error: error:140890C7:
SSL routines:ssl3_get_client_certificate:
peer did not return a certificate --
No CAs known to server for verification?
There could be any of several reasons for this problem:
Docusign was not configured to respond to the mutual TLS certificate request. Ensure that the Enable Mutual TLS option is checked.
Or the root distinguished name sent to the client during the handshake was either missing or wrong.
Or the CertificateRequest message didn't include a Hash Algorithm / Signature Algorithm pair that the client supports.
To drill down further, you can request log level ssl:trace8. This will include the actual TLS handshake protocol contents in the apache2 error file.
Frequently asked questions
What Docusign setting enables Mutual TLS?
If you’re using the Administration tool to configure your Connect configuration, check the Enable Mutual TLS option**.**
If you’re programmatically creating the Connect configuration, set the signMessageWithX509Certificate field to “true”.
If you’re using the eventNotification settings in the Envelopes: create method, set the signMessageWithX509Cert field to “true”.
It is not necessary to use the “Require Mutual TLS” field and setting only that field is not sufficient.
Is setting Docusign to enable Mutual TLS, the Enable Mutual TLS option, enough to turn on Mutual TLS?
No. Mutual TLS also needs to be correctly configured on the webserver (or proxy) that negotiates the TLS protocol with the DocuSIgn Connect client. Mutual TLS must be requested by the server (the Connect listener). Mutual TLS cannot be initiated by Docusign.
If DocuSIgn is configured to enable Mutual TLS, will the Connect notification work if the server (the application’s listener) does not request/support Mutual TLS?
Yes, the notification POST message from Docusign will work with or without Mututal TLS in this case.
Is there a way to configure Docusign to require that Mutual TLS be used?
No. That is the intent of the Docusign “Require Mutual TLS” setting, but that feature has a bug at this time.
Note that Mutual TLS is a useful but not sufficient defense, access control should also be used and access control is only possible on the server.
Web servers have a setting that requires clients to support Mutual TLS.
I’d like the notification message to be digitally signed in addition to Mutual TLS. Is that option available?
No, only one or the other is available for a Connect configuration. If Mutual TLS is enabled, then the option for digitally signing the notification messages is ignored. The notification messages won’t be digitally signed even if Mutual TLS is enabled but not in use.
I understand that the Mutual TLS Request Certificate handshake message includes one or more distinguished names that the server trusts. What else does it contain?
The Client Request message also includes certificate types and pairs of Hash Algorithm / Signature Algorithm names that the server will accept from the client. The Docusign client certificates use the SHA256 hash algorithm, so it must be included in the list of acceptable hash algorithms sent by the server.
Summary
For a secure webhook configuration, Mutual TLS plus Access Control is an important defense. It’s implemented at your app’s web server. The alternative, digitally signed Connect messages, is handled by your app. The two provide equivalent defenses. Use the one which best fits your organization.
Additional resources
Please let us know your experiences. Write us via developers@docusign.com. I'll be speaking at our MOMENTUM '17 conference in San Francisco from May 3-4. Developers can attend for free. Learn more and register for MOMENTUM '17 here.
Updates
This post was updated on February 13, 2017 to include information about the 1024 bit root certificate that can also be used to verify the Docusign Connect certificate and its included intermediate bundle.
This post was updated on May 17, 2018 to reflect the updated NDSE control panel for Connect. The checkbox for Mutual TLS has been renamed to be Enable Mutual TLS.
Larry Kluger has over 40 years of tech industry experience as a software developer, developer advocate, entrepreneur, and product manager. An award-winning speaker prominent StackOverflow contributor, he enjoys giving talks and helping the ISV and developer communities.
Twitter: @larrykluger
LinkedIn: https://www.linkedin.com/in/larrykluger/
Related posts