ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop on the web portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
    Develop locally with the CLI
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
Concepts
Development
Policies
    Policy Catalog
    Authentication
      API Key AuthenticationAuth0 JWT AuthClerk JWT AuthAWS Cognito JWT AuthFirebase JWT AuthOkta JWT AuthJWT AuthPropelAuth JWT AuthSupabase JWT AuthCurity Phantom Token AuthBasic AuthmTLS AuthLDAP Auth
    Authorization
    MCP Authorization
    Security & Validation
    Metrics, Billing & Quotas
    Testing
    Request Modification
    Response Modification
    Upstream Authentication
    GraphQL
    Other
    Guides
Handlers
API Keys
Rate Limiting
MCP Server
MCP Gateway
AI Gateway
Developer Portal
Monetization
GraphQL
Deploying & Source Control
Analytics
Observability
Networking & Infrastructure
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsSecuritySupportTrust & ComplianceChangelog
powered by Zudoku
Authentication

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:

  1. 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.
  2. Add this policy (mtls-auth-inbound) to each route that should require a verified client certificate, and set certIssuerDN to pin the issuer (see the options described below).
  3. Read the certificate in your request handler or downstream policies from request.user.data.mtlsAuth.
  4. 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-certificate CLI 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
{ "name": "my-mtls-auth-inbound-policy", "policyType": "mtls-auth-inbound", "handler": { "export": "MTLSAuthInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "allowUnauthenticatedRequests": false, "certIssuerDN": "CN=example-ca, O=Example, C=US" } } }

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 be mtls-auth-inbound.
  • handler.export <string> - The name of the exported type. Value should be MTLSAuthInboundPolicy.
  • 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 unless allowUnauthenticatedRequests is true. 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 to false.

Using the Policy

Read more about how policies work

Edit this page
Last modified on July 25, 2026
Basic AuthLDAP Auth
On this page
  • Setting up client mTLS
  • How the policy behaves
  • Learn more
  • Configuration
    • Policy Configuration
    • Policy Options
  • Using the Policy
JSON