Mutual TLS (mTLS) authentication ensures that traffic is both secure and trusted in both directions between a client and server. It allows requests that do not log in with an identity provider (like IoT devices) to demonstrate that they can reach a given resource. Client certificate authentication is also a second layer of security for team members who both log in with an identity provider (IdP) and present a valid client certificate.
With a root certificate authority (CA) in place, Access only allows requests from devices with a corresponding client certificate. When a request reaches the application, Access responds with a request for the client to present a certificate. If the device fails to present the certificate, the request is not allowed to proceed. If the client does have a certificate, Access completes a key exchange to verify.
To enforce mTLS authentication from the Cloudflare dashboard:
Open the Access app and scroll to the Mutual TLS Root Certificates card. Click Add a New Certificate.
The Root Certificate dialog opensd.
Assign the root certificate authority a name.
Paste the root certificate authority certificate in PEM format in the Certificate content field.
If your zone is using an intermediate certificate in addition to the root certificate, upload the entire chain.
In the Associated Hostnames field, input the hostnames for enforcing mTLS authentication.
You must associate the certificate with a hostname because paths cannot be associated. These must be hostnames configured in your account.
Create an Access policy.
Apply the policy to the path to protect.
Under the Policies section, name the policy and select Non Identity as the Decision.
Under Include, select Valid Certificate from the drop-down menu.
This populates with the certificate associated with this hostname.
You can now use
curl to test the operation.
Test for the site using mTLS by attempting to
curl the site without a client certificate.
curl command example is for the site
example.com that has an Access policy set for
curl -sv https://auth.example.com
Without a client certificate in the request, a “403 forbidden” response displays and the site cannot be accessed.
Add your client certificate information to the request:
curl -sv https://auth.example.com --cert example.pem --key key.pem
When the authentication process completes successfully, a
CF_Authorization Set-Cookie header returns in the response.
Cloudflare Access evaluates every request to your application based on your rule set. Client certificates allow request authentication when you are not using an identity provider (like IoT devices). When you use an IdP, mTLS authentication adds a second layer of security to control who can reach your application.
This is the validation workflow when you enable this Access policy:
Access evaluates all requests to the origin for a valid client certificate.
The client device sends the client
“hello”. Cloudflare Access responds with
“hello” and a request for the client certificate.
The client returns a valid certificate.
Cloudflare Access completes the client authentication handshake against the root certificate authority and, if applicable, intermediate variables that were configured for the policy.
For chains, Access checks for expired certificates.
Chain verification is applicable to certificate validation.
When the client certificate is trusted by the root certificate, Cloudflare Access generates a signed JSON Web Token (JWT) for the client that allows the request and subsequent requests to proceed.
If a request has no valid client certificate, 403 Forbidden returns in the response.
By default, Cloudflare Access generates and signs a JWT for all requests that complete a successful mTLS handshake. The token is valid for the session duration configured in the Access policy. Teams can configure automated services to reuse the token in subsequent requests. When mTLS is a component of users authenticating to a service, this removes the burden of an individual completing the client certificate prompt in their browser on each request.
In some cases, particularly IoT examples, the expected behavior is that Access will force a new mTLS handshake for each request. This is when a token is not required, and you must ensure that the token expires immediately to remove the risk of reuse.
To edit session duration from the Access app, open the Edit Access Policy dialog and select No Duration from the Session Duration drop-down list. Cloudflare still generates a token, but the token is only valid for the lifecycle of an individual request, and is not sent in the response.