Documentation Index Fetch the complete documentation index at: https://developers.cloudflare.com/cloudflare-one/llms.txt Use this file to discover all available pages before exploring further.
Mutual TLS (mTLS) authentication ↗ requires both the client and the server to present certificates during the TLS handshake. In the Cloudflare Access implementation, the CA you upload is used to verify the client certificate (server certificate verification is handled by standard TLS). Access mTLS serves two purposes:
Authenticate devices that do not use an identity provider — Automated systems and IoT devices can prove their identity by presenting a client certificate instead of logging in through an IdP.
Add a second authentication factor — Team members who log in through an IdP can also be required to present a valid client certificate, providing an additional layer of security.
When you upload a root certificate authority (CA) to Access, only requests from devices with a matching client certificate are allowed through. When a request reaches the application, Access asks the client to present a certificate. If the client cannot present a valid certificate, the request is blocked. If the client presents a valid certificate, Access completes a key exchange to verify.
Enforce mTLS authentication
Prerequisites
An Access application for the hostname that you would like to secure with mTLS.
A CA that issues client certificates for your devices.
The CA certificate can be from a publicly trusted CA or self-signed.
In the certificate Basic Constraints, the attribute CA must be set to TRUE.
The certificate must use one of the signature algorithms listed below:
Allowed signature algorithms
x509.SHA1WithRSA
x509.SHA256WithRSA
x509.SHA384WithRSA
x509.SHA512WithRSA
x509.ECDSAWithSHA1
x509.ECDSAWithSHA256
x509.ECDSAWithSHA384
x509.ECDSAWithSHA512
Add mTLS to your Access application
In the Cloudflare dashboard ↗, go to Zero Trust > Access controls > Service credentials > Mutual TLS.
Select Add mTLS Certificate.
Enter any name for the root CA.
In Certificate content, paste the contents of your root CA.
If the client certificate is directly signed by the root CA, you only need to upload the root. If the client certificate is signed by an intermediate certificate, you must upload the entire CA chain (intermediate and root). For example:
Do not include any SSL/TLS server certificates; Access only uses the CA chain to verify the connection between the user's device and Cloudflare.
In Associated hostnames, enter the fully-qualified domain names (FQDN) that will use this certificate.
These FQDNs will be the hostnames used for the resources being protected in the Access policy. You must associate the Root CA with the FQDN that the application being protected uses.
Valid Certificate: Any client certificate that can authenticate with the Root CA will be allowed to proceed.
Common Name: Only client certificates with a specific common name will be allowed to proceed.
If this is for a client who does not need to log in through an IdP, set the policy Action to Service Auth.
Example mTLS policy
Action
Rule type
Selector
Value
Service Auth
Include
Common Name
John Doe
Save the policy, then go to Access controls > Applications.
Select the application you would like to enforce mTLS on and select Configure. The application must be included in the Associated hostnames list from Step 5.
In the Policies tab, add your mTLS policy.
Save the application.
You can now authenticate to the application using a client certificate. For instructions on how to present a client certificate, refer to Test mTLS.
Test mTLS
Test using cURL
To test the application protected by an mTLS policy:
First, attempt to curl the site without a client certificate.
This curl command example is for the site example.com that has an Access application and policy set for https://auth.example.com:
curl -sv https://auth.example.com
Without a client certificate in the request, a 403 forbidden response displays and the site cannot be accessed.
Now, add your client certificate and key to the request:
When the authentication process completes successfully, a CF_Authorization Set-Cookie header returns in the response.
Test in a browser
To access an mTLS-protected application in a browser, the client certificate must be imported into your browser's certificate manager. Instructions vary depending on the browser. Your browser may use the operating system's root store or its own internal trust store.
The following example demonstrates how to add a client certificate to the macOS system keychain:
Navigate to the directory containing the client certificate and key.
Open the client.pem file in Keychain Access. If prompted, enter your local password.
In Keychain, choose the access option that suits your needs and select Add.
In the list of certificates, locate the newly installed certificate. Keychain Access will mark this certificate as not trusted. Right-click the certificate and select Get Info.
Select Trust. Under When using this certificate, select Always Trust.
Assuming your browser uses the macOS system store, you can now connect to the mTLS application through the browser.
Generate mTLS certificates
You can use open source private key infrastructure (PKI) tools to generate certificates to test the mTLS feature in Cloudflare Access.
OpenSSL
This section covers how to use OpenSSL ↗ to generate a root and intermediate certificate, and then issue client certificates that can authenticate against the CA chain.
Generate the root CA
Generate the root CA private key:
openssl genrsa -aes256 -out rootCA.key 4096
When prompted, enter a password to use with rootCA.key.
Create a self-signed root certificate called rootCA.pem:
You will be prompted to enter your private key password and fill in some optional fields. For testing purposes, you can leave the optional fields blank.
Generate an intermediate certificate
Generate the intermediate CA private key:
openssl genrsa -aes256 -out intermediate.key 4096
When prompted, enter a password to use with intermediate.key.
Create a certificate signing request (CSR) for the intermediate certificate:
You will be prompted to enter your private key password and fill in some optional fields. For testing purposes, you can leave the optional fields blank.
Create a CA Extension file called v3_intermediate_ca.ext. For example,
Make sure that basicConstraints includes the CA:true property. This property allows the intermediate certificate to act as a CA and sign client certificates.
Sign the intermediate certificate with the root CA:
Validate the client certificate against the certificate chain:
openssl verify -CAfile ca-chain.pem client.pem
client.pem: OK
You can now use the client certificate (client.pem) and its key (client.key) to test mTLS.
Cloudflare PKI
This guide uses Cloudflare's PKI toolkit ↗ to generate a root CA and client certificates from JSON files.
1. Install dependencies
The process requires two packages from Cloudflare's PKI toolkit:
cf-ssl
cfssljson
You can install these packages from the Cloudflare SSL GitHub repository ↗. You will need a working installation of Go, version 1.12 or later. Alternatively, you can download the packages ↗ directly.
Use the instructions under Installation to install the toolkit, and ensure that you install all of the utility programs in the toolkit.
2. Generate the root CA
Create a new directory to store the root CA.
Within that directory, create two new files:
CSR. Create a file named ca-csr.json and add the following JSON blob, then save the file.
The command will output a client certificate file (client.pem) and its key (client-key.pem). You can now use these files to test mTLS.
Create a certificate revocation list
You can use the Cloudflare PKI toolkit to generate a certificate revocation list (CRL), as well. This list will contain client certificates that are revoked.
Get the serial number from the client certificate generated earlier. Add that serial number, or any others you intend to revoke, in hex format in a text file. This example uses a file named serials.txt.
You will need to add the CRL to your server or enforce the revocation in a Cloudflare Worker. An example Worker Script can be found on the Cloudflare GitHub repository ↗.
Add Client-Cert and Client-Cert-Chain headers (RFC 9440)
RFC 9440 ↗ defines the Client-Cert and Client-Cert-Chain HTTP header fields for passing client certificate information to origin servers. You can construct these headers using request header modification rules with the following Ruleset Engine fields:
As indicated in field definitions, the fields may be set to either an empty string or a valid RFC 9440 encoding. Proper usage depends on a couple of factors discussed in the following sections.
Security considerations
The cert_rfc9440 and cert_chain_rfc9440 fields are populated regardless of the certificate validation result. This means a client can present an invalid, expired, or self-signed certificate, and the fields will still contain the encoded certificate data. Always check the following fields before trusting the values:
A client can also include its own Client-Cert or Client-Cert-Chain headers on a request to inject arbitrary values. As described in the RFC 9440 security considerations ↗, you must unconditionally remove any existing Client-Cert and Client-Cert-Chain headers from incoming requests, regardless of certificate validity. This prevents a client from injecting forged certificate data that your origin would trust.
See Enable mTLS for details on how to configure mTLS and certificate validation.
Size limits
The encoded leaf certificate is limited to 10 KiB and the encoded chain is limited to 16 KiB. If the encoded value exceeds the limit, the corresponding field contains an empty string. Use the following fields to check for this condition:
Here we provide an example on how to securely use these fields to construct trusted Client-Cert and Client-Cert-Chain headers to be forwarded to your origin.
The origin can then rely on the presence of the headers to be certain the client presented a valid certificate.
Note: the Client-Cert-Chain header may be omitted when the client did not present any intermediates (only a leaf certificate).
You need to create the following request header modification rules.
The Remove rules must be placed before the Set dynamic rules
so that client-injected headers are stripped on every request before the validated values are set.
Rule 1 — Remove Client-Cert header
This rule unconditionally removes any Client-Cert header sent by the client.
Text in Expression Editor:
true
Selected operation under Modify request header: Remove
Header name: Client-Cert
Rule 2 — Remove Client-Cert-Chain header
This rule unconditionally removes any Client-Cert-Chain header sent by the client.
Text in Expression Editor:
true
Selected operation under Modify request header: Remove
Header name: Client-Cert-Chain
Rule 3 — Set Client-Cert header
This rule sets the Client-Cert header only when the client presented a valid, non-revoked certificate that is within the size limit.
Text in Expression Editor:
cf.tls_client_auth.cert_verifiedand not cf.tls_client_auth.cert_revokedand not cf.tls_client_auth.cert_rfc9440_too_large
Selected operation under Modify request header: Set dynamic
Header name: Client-Cert
Value: cf.tls_client_auth.cert_rfc9440
Rule 4 — Set Client-Cert-Chain header
This rule sets the Client-Cert-Chain header only when the client presented a valid, non-revoked certificate
and the chain is non-empty and within the size limit.
Text in Expression Editor:
cf.tls_client_auth.cert_verifiedand not cf.tls_client_auth.cert_revokedand cf.tls_client_auth.cert_chain_rfc9440 ne ""and not cf.tls_client_auth.cert_chain_rfc9440_too_large
Selected operation under Modify request header: Set dynamic
Header name: Client-Cert-Chain
Value: cf.tls_client_auth.cert_chain_rfc9440
Cloudflare Workers
You can also construct RFC 9440 headers in a Cloudflare Worker
using the tlsClientAuth
properties on the incoming request.
The same security considerations mentioned above apply.
Forward a client certificate (legacy)
In addition to enforcing mTLS authentication for your host, you can also forward a client certificate to your origin server as an HTTP header. This setup is often helpful for server logging.
To avoid adding the certificate to every single request, the certificate is only forwarded on the first request of an mTLS connection.
Cloudflare R2 public bucket served on a custom domain
Notifications for mutual TLS certificates
Cloudflare will send the following notifications before your mutual TLS certificates expire:
Access mTLS Certificate Expiration Alert
Who is it for?
Access customers that use client certificates for mutual TLS authentication. This notification will be sent 30 and 14 days before the expiration of the certificate.