mTLS Auth Policy
The mtls-auth-inbound policy is the enforcement step of client mutual TLS
(mTLS). It reads the verification result that Zuplo's edge proxy attaches to
each request and, when enforcement is enabled, rejects requests that don't
present a valid client certificate signed by a CA you trust. It is one part of a
complete client mTLS setup: you first upload the signing CA to your account,
then add this policy to the routes you want to protect.
For the full walkthrough — CA upload, configuration, testing with curl,
rotation, and troubleshooting (including the common
FAILED to get issuer certificate error) — see the
Client mTLS authentication guide.
Setting up client mTLS
This policy only enforces a result; it does not, on its own, make Zuplo verify client certificates. The end-to-end setup is:
- Upload your CA certificate to your account with the
Zuplo CLI:
zuplo ca-certificate create --name my_ca --cert ./ca.pem --account your-account. Upload the self-signed root CA that anchors the chain, not an intermediate. CA certificates are scoped to your account, so once uploaded, every gateway domain on the account verifies presented client certificates against it. - Add this policy (
mtls-auth-inbound) to each route that should require a verified client certificate, and setcertIssuerDNto pin the issuer (see the options described below). - Read the certificate in your request handler or downstream policies from
request.user.data.mtlsAuth. - Test with a client certificate issued by (or chained to) your CA:
curl --cert ./client.pem --key ./client.key https://your-gateway.zuplo.app/v1/example.
See the full guide for CA management, custom domains, rotation, and troubleshooting.
How the policy behaves
When enforcement is enabled, the policy rejects requests where no client certificate was presented, certificate verification failed, or the certificate metadata cannot be parsed.
When verification passes, the policy parses the client certificate metadata and
sets it on request.user.data.mtlsAuth. The metadata includes subject,
issuer, notBefore, notAfter, and, when available, sha256Fingerprint. If
request.user already exists, its sub is preserved. Otherwise, the policy
creates request.user with the certificate subject as sub.
Set allowUnauthenticatedRequests to true to enable passthrough mode. In
passthrough mode, requests are allowed even when mTLS verification fails or no
certificate is present. If a parseable certificate is present, the policy still
sets request.user.data.mtlsAuth; otherwise it leaves the request unchanged.
Set certIssuerDN to the fully qualified issuer distinguished name to require
on the client certificate. The policy rejects certificates whose parsed issuer
DN does not match. certIssuerDN is required whenever enforcement is enabled
(i.e. when allowUnauthenticatedRequests is not true); the policy fails to
load otherwise. This guarantees that requests are pinned to a specific CA and is
especially important when an account has multiple CAs configured.
Comparison is order-sensitive on RDNs (e.g. "CN=foo, O=bar" does not match
"O=bar, CN=foo", which matches RFC 4514 §2.1 semantics) but tolerant of casing
and whitespace, so "CN=example-ca, O=Example, C=US" matches
"cn=Example-CA,o=example,c=us". Multi-valued RDNs (+) and hex-encoded values
(#...) are not normalized. The simplest way to obtain the expected value is to
inspect request.user.data.mtlsAuth.issuer from a request signed by the desired
CA.
Note: this policy does not work with local development since it relies on metadata from the upstream reverse proxy. It is recommended to test this using a working-copy or preview environment.
Learn more
- Client mTLS authentication guide — full end-to-end setup, CA management, and troubleshooting
ca-certificateCLI reference — upload, list, describe, rename, and delete account CA certificates- Gateway to Origin mTLS — the reverse direction, where Zuplo authenticates to your backend with a client certificate
Enterprise Feature
This policy is only available as part of our enterprise plans. It's free to try only any plan for development only purposes. If you would like to use this in production reach out to us: sales@zuplo.com
Configuration
The configuration shows how to configure the policy in the 'policies.json' document.
Code
Policy Configuration
name<string>- The name of your policy instance. This is used as a reference in your routes.policyType<string>- The identifier of the policy. This is used by the Zuplo UI. Value should bemtls-auth-inbound.handler.export<string>- The name of the exported type. Value should beMTLSAuthInboundPolicy.handler.module<string>- The module containing the policy. Value should be$import(@zuplo/runtime).handler.options<object>- The options for this policy. See Policy Options below.
Policy Options
The options for this policy are specified below. All properties are optional unless specifically marked as required.
certIssuerDN<string>- Fully qualified issuer distinguished name to require on the client certificate. The policy rejects certificates whose parsed issuer DN does not match this string exactly. Required unlessallowUnauthenticatedRequestsistrue. The expected format matches the parsed metadata issuer, e.g. "CN=example-ca, O=Example, C=US".allowUnauthenticatedRequests<boolean>- Allows requests to continue even when mTLS verification fails, no client certificate is presented, or the certificate metadata cannot be parsed. Defaults to false. Defaults tofalse.
Using the Policy
Read more about how policies work