Text in Expression Editor:
trueSelected operation under Modify request header: Remove
Header name: Client-Cert
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:
cf.tls_client_auth.cert_rfc9440 — The client leaf certificate encoded in RFC 9440 formatting (see reference).cf.tls_client_auth.cert_chain_rfc9440 — The certificate chain (excluding the leaf certificate) encoded in RFC 9440 formatting (see reference).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.
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:
cf.tls_client_auth.cert_verified — Returns true when the client certificate is valid.cf.tls_client_auth.cert_revoked — Returns true when the client certificate has been revoked.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.
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:
cf.tls_client_auth.cert_rfc9440_too_large — Returns true when the encoded certificate exceeds 10 KiB.cf.tls_client_auth.cert_chain_rfc9440_too_large — Returns true when the encoded chain exceeds 16 KiB.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.
This rule unconditionally removes any Client-Cert header sent by the client.
Text in Expression Editor:
trueSelected operation under Modify request header: Remove
Header name: Client-Cert
This rule unconditionally removes any Client-Cert-Chain header sent by the client.
Text in Expression Editor:
trueSelected operation under Modify request header: Remove
Header name: Client-Cert-Chain
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_largeSelected operation under Modify request header: Set dynamic
Header name: Client-Cert
Value: cf.tls_client_auth.cert_rfc9440
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_largeSelected operation under Modify request header: Set dynamic
Header name: Client-Cert-Chain
Value: cf.tls_client_auth.cert_chain_rfc9440
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.
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.
The most common approach to forwarding a certificate is to use the Cloudflare API to update an mTLS certificate's hostname settings.
Required API token permissions
Access: Mutual TLS Certificates Writecurl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/access/certificates/settings" \ --request PUT \ --header "X-Auth-Email: $CLOUDFLARE_EMAIL" \ --header "X-Auth-Key: $CLOUDFLARE_API_KEY" \ --json '{ "settings": [ { "hostname": "<HOSTNAME>", "china_network": false, "client_certificate_forwarding": true } ] }'Once client_certificate_forwarding is set to true, every request within an mTLS connection will now include the following headers:
Cf-Client-Cert-Der-Base64Cf-Client-Cert-Sha256You can also modify HTTP response headers using Managed Transforms to pass along TLS client auth headers.
Additionally, Workers can provide details around the client certificate.
const tlsHeaders = { "X-CERT-ISSUER-DN": request.cf.tlsClientAuth.certIssuerDN, "X-CERT-SUBJECT-DN": request.cf.tlsClientAuth.certSubjectDN, "X-CERT-ISSUER-DN-L": request.cf.tlsClientAuth.certIssuerDNLegacy, "X-CERT-SUBJECT-DN-L": request.cf.tlsClientAuth.certSubjectDNLegacy, "X-CERT-SERIAL": request.cf.tlsClientAuth.certSerial, "X-CERT-FINGER": request.cf.tlsClientAuth.certFingerprintSHA1, "X-CERT-VERIFY": request.cf.tlsClientAuth.certVerify, "X-CERT-NOTBE": request.cf.tlsClientAuth.certNotBefore, "X-CERT-NOTAF": request.cf.tlsClientAuth.certNotAfter,};