# mTLS Auth Policy

This policy verifies client mTLS results supplied by Zuplo's edge proxy. It
checks the incoming mTLS verification status and, when enforcement is enabled,
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 `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.

:::info{title="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](mailto:sales@zuplo.com)

:::

## Configuration

The configuration shows how to configure the policy in the 'policies.json' document.

```json title="config/policies.json"
{
  "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` <code className="text-green-600">&lt;string&gt;</code> - The name of your policy instance. This is used as a reference in your routes.
- `policyType` <code className="text-green-600">&lt;string&gt;</code> - The identifier of the policy. This is used by the Zuplo UI. Value should be `mtls-auth-inbound`.
- `handler.export` <code className="text-green-600">&lt;string&gt;</code> - The name of the exported type. Value should be `MTLSAuthInboundPolicy`.
- `handler.module` <code className="text-green-600">&lt;string&gt;</code> - The module containing the policy. Value should be `$import(@zuplo/runtime)`.
- `handler.options` <code className="text-green-600">&lt;object&gt;</code> - The options for this policy. [See Policy Options](#policy-options) below.

### Policy Options

The options for this policy are specified below. All properties are optional unless specifically marked as required.

- `allowUnauthenticatedRequests` <code className="text-green-600">&lt;boolean&gt;</code> - 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`.
- `certIssuerDN` <code className="text-green-600">&lt;string&gt;</code> - 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".

## Using the Policy

Read more about [how policies work](/articles/policies)
