> ## Documentation Index
> Fetch the complete documentation index at: https://infisical.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# TLS certificate auth

> Learn how to authenticate with Infisical using TLS Certificate.

**TLS Certificate Auth** is an authentication method that verifies a user's TLS Client certificate using the provided CA Certificate, allowing secure access to Infisical resources.

## Diagram

The following sequence diagram illustrates the TLS Certificate Auth workflow for authenticating users with Infisical.

```mermaid theme={"dark"}
sequenceDiagram
  participant Client
  participant Infisical

  Note over Client,Client: Step 1: Setup your TLS request with the client certificate

  Note over Client,Infisical: Step 2: Login Operation
  Client->>Infisical: Send request to /api/v1/auth/tls-cert-auth/login

  Note over Infisical: Step 3: Request verification using CA Certificate

  Infisical->>Client: Return short-lived access token

  Note over Client,Infisical: Step 5: Access Infisical API with token
  Client->>Infisical: Make authenticated requests using the short-lived access token
```

## Concept

At a high level, Infisical authenticates the client's TLS Certificate by verifying its identity and checking that it meets specific requirements (e.g., it is bound to the allowed common names) at the `/api/v1/auth/tls-cert-auth/login` endpoint. If successful, Infisical returns a short-lived access token that can be used to make authenticated requests to the Infisical API.

To be more specific:

1. The client sends a TLS request with the client certificate to Infisical at the `/api/v1/auth/tls-cert-auth/login` endpoint.
2. Infisical verifies the incoming request using the provided CA certificate.
3. Infisical checks the user's properties against set criteria such as Allowed Common Names and Allowed Subject Alternative Names.
4. If all checks pass, Infisical returns a short-lived access token that the client can use to make authenticated requests to the Infisical API.

> [accordion] TLS with Load Balancer/Proxy
>
> Most of the time, the Infisical server will be behind a load balancer or
> proxy. To propagate the TLS certificate from the load balancer to the
> instance, you can configure the TLS to send the client certificate as a header
> that is set as an [environment variable](https://infisical.com/docs/self-hosting/configuration/envars.md#param-identity-tls-cert-auth-client-certificate-header-key).

> [!NOTE]
>
> Infisical US/EU and dedicated instances are deployed with AWS ALB. TLS Certificate Auth must flow through our ALB mTLS pass-through in order to authenticate.
> When you're authenticating with TLS Certificate Auth, you must use the port `8443` instead of the default `443`. Example: `https://app.infisical.com:8443/api/v1/auth/tls-cert-auth/login`

## Guide

In the following steps, we explore how to create and use identities for your workloads and applications on TLS Certificate to
access the Infisical API using request signing.

> [!WARNING]
>
> **Self-Hosted Users:** Before using TLS Certificate Auth, please review the
> [Security Requirements for Self-Hosted
> Deployments](#security-requirements-for-self-hosted-deployments) section below
> to ensure proper configuration and avoid security vulnerabilities.

### Creating an identity

To create an identity, go to **Access Control** > [**Machine Identities**](https://app.infisical.com/organization/access-management?selectedTab=identities) in your organization and select **Create**.

![identities organization](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/identities/identities-org.png)

When creating an identity, you specify an organization-level [role](https://infisical.com/docs/documentation/platform/access-controls/role-based-access-controls.md) for it to assume; you can configure roles in **Access Control** > [Roles](https://app.infisical.com/organization/access-management?selectedTab=roles).

![identities organization create](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/identities/identities-org-create.png)

Input some details for your new identity:

* **Name (required):** A friendly name for the identity.
* **Role (required):** A role from the [**Organization Roles**](https://app.infisical.com/organization/access-management?selectedTab=roles) tab for the identity to assume. The organization role assigned will determine what organization-level resources this identity can have access to.

Once you've created an identity, you'll be redirected to a page where you can manage the identity.

![identities page](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/identities/identities-page.png)

Since the identity has been configured with [Universal Auth](https://infisical.com/docs/documentation/platform/identities/universal-auth.md) by default, you should reconfigure it to use TLS Certificate Auth instead. To do this, select the three dot menu next to **Universal Auth**, then select **Remove Auth Method**.

![identities press cog](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/identities/identities-press-cog.png)

![identities page remove default auth](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/identities/identities-page-remove-default-auth.png)

Now create a new TLS Certificate Auth Method.

![identities create tls cert auth method](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/identities/identities-tls-cert-auth-create-auth.png)

Here's some information about each field:

* **CA Certificate:** A PEM encoded CA Certificate used to validate incoming TLS request client certificate. Any name constraints it asserts are honored, so a client certificate whose name falls outside the namespace the CA may certify is rejected. Both the CA Certificate and the client certificate must permit client authentication: a certificate that lists an Extended Key Usage without `clientAuth` (or `anyExtendedKeyUsage`) is rejected, since a CA's key usages also limit what the certificates beneath it may be used for. A certificate that lists no Extended Key Usage is unrestricted and is accepted.
* **Verify Client Certificate Chain (default is disabled):** By default, the CA Certificate must be the **direct issuer** of the client's leaf certificate. Enable this to instead treat the CA Certificate as a **trust anchor** and accept any client whose presented chain (leaf followed by intermediates) builds a valid path up to it. This is helpful when the issuing intermediate rotates beneath a long-lived root, such as a **SPIRE X.509-SVID**: you can pin the stable root here once and let the workload present its current intermediate alongside its leaf, rather than updating the CA Certificate on every rotation. Either way the trust anchor is the only certificate trusted, the client certificate must still be an end-entity certificate, and the Common Name and Subject Alternative Name checks below still apply to the leaf. Restrictions that the CAs on the path place on their subordinates are honored: a client certificate whose name falls outside an issuing CA's name constraints is rejected, as is a chain with more intermediates than a CA's path length permits, or one that passes through a CA whose Extended Key Usage doesn't permit client authentication.
* **Bind Access Tokens to Client Certificate (default is disabled):** Binds each issued access token to the client certificate used to log in. See [Certificate-bound access tokens](#certificate-bound-access-tokens).
* **Allowed Common Names:** A comma separated list of client certificate common names allowed.
* **Allowed Subject Alternative Names:** A comma separated list of client certificate subject alternative names (SANs) allowed. This is useful when the client certificate carries its identity in a SAN rather than the Subject Common Name, such as a SPIFFE X.509-SVID whose identity is a URI SAN (`spiffe://trust-domain/path`) with an empty Subject. Matching is type-aware, so an entry only matches a SAN of the same type:

  * **Type-prefixed entries** are matched against the corresponding SAN type, e.g. `URI:spiffe://example.org/svc`, `IP:10.0.0.1`, `EMAIL:svc@example.com`.
  * **Bare entries** (no prefix) are treated as **DNS** names, e.g. `svc.example.com`. DNS and email matching is case-insensitive; URI and IP values are matched exactly.

  When both Allowed Common Names and Allowed Subject Alternative Names are set, the certificate must satisfy both checks. Leave empty to skip SAN validation.
* **Access Token TTL (default is `2592000` equivalent to 30 days):** The lifetime for an access token in seconds. This value will be referenced at renewal time.
* **Access Token Max TTL (default is `2592000` equivalent to 30 days):** The maximum lifetime for an access token in seconds. This value will be referenced at renewal time.
* **Access Token Max Number of Uses (default is `0`):** The maximum number of times that an access token can be used; a value of `0` implies an infinite number of uses.
* **Access Token Trusted IPs:** The IPs or CIDR ranges that access tokens can be used from. By default, each token is given the `0.0.0.0/0`, allowing usage from any network address.

> [!NOTE]
>
> If your CA restricts the namespace it may certify through the X.509 **name constraints** extension,
> those restrictions are enforced on every login, in both single-hop and chain mode. A URI name
> constraint restricts the **host** only and must be a fully qualified domain name, such as
> `example.org` or `.example.org`. Writing it the way the identity itself looks, such as
> `spiffe://example.org`, or writing one that carries a path, isn't a hostname, so no client
> certificate can satisfy it and every login is denied. Infisical rejects such a CA Certificate when you save it.
>
> A client certificate that carries several names of a constrained type has to keep **every** one of
> them inside the permitted namespace. Pairing an in-scope name with an out-of-scope one doesn't
> make the out-of-scope name acceptable; the login is denied.
>
> Name constraints can't scope individual workloads, because a URI constraint applies to the host
> and ignores the path. Use **Allowed Subject Alternative Names** for that.

### Adding an identity to a project

In order to allow an identity to access project-level resources such as secrets, you must add it to the relevant projects.

To do this, open the project you want to add the identity to, go to **Access Control** > **Machine Identities**, and select **Add Machine Identity to Project**.

![identities project](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/identities/identities-project.png)

Select the identity you want to add to the project and the project-level role you want it to assume. The project role given to the identity will determine what project-level resources this identity can access.

![identities project create](https://mintlify.s3.us-west-1.amazonaws.com/infisical/images/platform/identities/identities-project-create.png)

### Accessing the Infisical API with the identity

To access the Infisical API as the identity, you need to send a TLS request to `/api/v1/auth/tls-cert-auth/login` endpoint.

Below is an example of how you can authenticate with Infisical using NodeJS.

```javascript theme={"dark"}
const fs = require("fs");
const https = require("https");
const axios = require("axios");

try {
  const clientCertificate = fs.readFileSync("client-cert.pem", "utf8");
  const clientKeyCertificate = fs.readFileSync("client-key.pem", "utf8");

  const infisicalUrl = "https://app.infisical.com:8443"; // or your self-hosted Infisical URL
  const identityId = "<your-identity-id>";

  // Create HTTPS agent with client certificate and key
  const httpsAgent = new https.Agent({
    cert: clientCertificate,
    key: clientKeyCertificate,
  });

  const { data } = await axios.post(
    `${infisicalUrl}/api/v1/auth/tls-cert-auth/login`,
    {
      identityId,
    },
    {
      httpsAgent: httpsAgent, // Pass the HTTPS agent with client cert
    }
  );

  console.log("result data: ", data); // access token here
} catch (err) {
  console.error(err);
}
```

> [!NOTE]
>
> Each identity access token has a time-to-live (TTL) which you can infer from the response of the login operation; the default TTL is `7200` seconds, which can be adjusted.
>
> If an identity access token expires, it can no longer access the Infisical API. A new access token should be obtained by performing another login operation.

## Certificate-bound access tokens

By default, an access token from TLS Certificate Auth is a bearer token: anyone holding it can use it. With **Bind Access Tokens to Client Certificate** enabled, the token also records the SHA-256 thumbprint of the client certificate used to log in, following [RFC 8705](https://www.rfc-editor.org/rfc/rfc8705) (the `cnf` claim with `x5t#S256`). A stolen token is then unusable without the certificate's private key.

With binding enabled:

* Every API request made with the token, including [token renewal](https://infisical.com/docs/api-reference/endpoints/universal-auth/renew-access-token.md), must present the same client certificate through the TLS-terminating proxy
* A request with no client certificate, or a different one, is rejected with `401 Unauthorized`
* Renewing the token keeps the binding
* After the client certificate rotates, the client must log in again to get a token bound to the new certificate

The client must present its certificate on every API call, not only on login. A custom client using the [login example](#accessing-the-infisical-api-with-the-identity) must reuse the same HTTPS agent for its later API calls. The [Infisical Issuer for cert-manager](https://infisical.com/docs/documentation/platform/pki/guides/applications/k8s-cert-manager-issuer.md) supports this through the `tlsCert` method.

On Infisical Cloud, send every API request made with a bound token to port `8443`, for example `https://app.infisical.com:8443`. Requests on port `443` carry no client certificate and are rejected.

Turning the setting on revokes the identity's existing TLS Certificate Auth tokens, which were issued without a binding. Tokens issued while the setting was on stay bound until they expire, even after it's turned off.

## Security requirements for self-hosted deployments

ALL TLS cert [login](https://infisical.com/docs/api-reference/endpoints/tls-cert-auth/login.md) requests **MUST** go through a load balancer/proxy that verifies certificate ownership:

* **REQUIRED:** Configure your load balancer/proxy to **require a proper TLS handshake with client certificate presentation**
* **REQUIRED:** Ensure the load balancer **verifies the client possesses the private key** corresponding to the certificate (standard TLS behavior)
* **NEVER** allow direct connections to Infisical for TLS cert auth, since this enables header injection attacks
* **NEVER** forward certificate headers without requiring proper TLS certificate presentation
* **REQUIRED:** Always overwrite the client certificate header with the certificate from the TLS handshake, or with an empty value when none was presented (certificates are public, and a client-supplied header lets anyone claim any certificate)

When **Bind Access Tokens to Client Certificate** is enabled on any identity, the proxy must set the header on **every** API request, not only on the login endpoint. Otherwise bound tokens are rejected on every request after login.

```nginx theme={"dark"}
server {
    listen 443 ssl;
    ssl_certificate /etc/nginx/tls/server.crt;
    ssl_certificate_key /etc/nginx/tls/server.key;
    ssl_verify_client optional_no_ca;

    location /api {
        proxy_set_header X-Identity-Tls-Cert-Auth-Client-Cert $ssl_client_escaped_cert;
        proxy_pass http://infisical:8080;
    }
}
```

`$ssl_client_escaped_cert` is empty when the client presents no certificate, so the header is cleared rather than passed through. Apply the same `proxy_set_header` in every `location` that proxies to the Infisical API.

### Load balancer configuration examples

* **AWS ALB:** Use mTLS listeners which require client certificate presentation during the TLS handshake
* **NGINX/HAProxy:** Configure SSL client certificate requirement with proper TLS handshake verification

> [!NOTE]
>
> Infisical will handle the actual certificate validation against the configured
> CA certificate and determine authentication permissions. The load balancer's
> role is to ensure certificate ownership, not certificate trust validation.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.