> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-api/connect/authentication/using-mtls.md).

# Using mTLS

Mutual TLS (mTLS) provides enhanced security for API communications by requiring both the client and server to authenticate each other using X.509 certificates. This guide explains how to use your Certta certificates to establish mTLS connections with Certta APIs.

## Overview

In traditional TLS, only the server authenticates itself to the client. In mTLS, both parties authenticate to each other:

1. Client initiates a connection to Certta API
2. Certta server presents its certificate
3. Client verifies the server certificate
4. Client presents its own certificate
5. Certta server verifies the client certificate
6. If both verifications succeed, a secure connection is established

This bidirectional authentication ensures that only trusted clients can access Certta APIs, and clients only connect to legitimate Certta servers.

## Prerequisites

Before implementing mTLS, ensure you have:

1. Access [Created a certificate](/caf-api/connect/authentication/certificates/creating-certificate.md) in the [Trust](https://trust.caf.io/)
2. Downloaded your client certificate (`.crt` file) and have your private key (`.key` file)
3. The correct Certta API endpoint for your production environment

{% hint style="info" %}
**API Endpoint**: For all mTLS-enabled API requests, use the base URL `https://mtls.us.prd.caf.io`. This is the production endpoint that supports mutual TLS authentication.
{% endhint %}

## Implementing mTLS in your application

### Converting certificate formats (if needed)

Depending on your programming language and framework, you might need to convert your certificate format:

**Converting .crt to other formats (if needed):**

```bash
# Convert .crt to .pem (if needed)
# In many cases, .crt and .pem are compatible, but some libraries prefer specific extensions
cp certificate.crt certificate.pem

# If you need to combine certificate and private key into PKCS#12 (.p12) format
openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt
```

### Code examples

Below are examples of implementing mTLS in various programming languages:

#### Java (OkHttp)

```java
import okhttp3.OkHttpClient;
import okhttp3.Request;

import javax.net.ssl.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

public class MtlsClient {
    public static void main(String[] args) throws Exception {
        // Load your certificate and private key files
        X509Certificate certificate = loadCertificate("certificate.crt");
        PrivateKey privateKey = loadPrivateKey("private.key");

        // Create a KeyManager with your certificate and private key
        KeyManager[] keyManagers = createKeyManagers(certificate, privateKey);

        // Create a TrustManager that trusts the server's certificate
        TrustManager[] trustManagers = createTrustManagers();

        // Create an SSL context with the key and trust managers
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagers, trustManagers, new SecureRandom());

        // Create an OkHttpClient with the SSL context
        OkHttpClient client = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0])
                .build();

        // Make a request to the `API`
        Request request = new Request.Builder()
                .url("https://mtls.us.prd.caf.io/v1/transactions")
                .build();

        client.newCall(request).execute();
    }

    private static X509Certificate loadCertificate(String filename) throws CertificateException, IOException {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        try (FileInputStream fis = new FileInputStream(filename)) {
            return (X509Certificate) factory.generateCertificate(fis);
        }
    }

    private static PrivateKey loadPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        // Read private key file (assumes PKCS#8 format)
        byte[] keyBytes = java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(filename));
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
    }

    private static KeyManager[] createKeyManagers(X509Certificate certificate, PrivateKey privateKey) throws Exception {
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);
        keyStore.setCertificateEntry("certificate", certificate);
        keyStore.setKeyEntry("private-key", privateKey, new char[0], new java.security.cert.Certificate[]{certificate});

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, new char[0]);
        return kmf.getKeyManagers();
    }

    private static TrustManager[] createTrustManagers() throws Exception {
        // For production use, you should use a proper trust store
        return new TrustManager[] {
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                public void checkServerTrusted(X509Certificate[] certs, String authType) {}
            }
        };
    }
}
```

#### Python (Requests)

```python
import requests

# Path to your certificate files
cert_file = "certificate.crt"
key_file = "private.key"

# Make a request to the `API`
response = requests.get(
    "https://mtls.us.prd.caf.io/v1/transactions",
    cert=(cert_file, key_file)
)

print(response.json())
```

#### Node.js

```javascript
const https = require("https");
const fs = require("fs");

// Read certificate files
const cert = fs.readFileSync("certificate.crt");
const key = fs.readFileSync("private.key");

// Configure the request options
const options = {
  hostname: "mtls.us.prd.caf.io",
  port: 443,
  path: "/v1/transactions",
  method: "GET",
  cert: cert,
  key: key,
};

// Make the request
const req = https.request(options, (res) => {
  let data = "";
  res.on("data", (chunk) => {
    data += chunk;
  });
  res.on("end", () => {
    console.log(JSON.parse(data));
  });
});

req.on("error", (error) => {
  console.error(error);
});

req.end();
```

#### Curl

Testing `mTLS` connections from the command line can be helpful for debugging. Here's how to use curl with `mTLS` certificates:

```bash
# Basic `mTLS` request
curl --cert certificate.crt --key private.key https://mtls.us.prd.caf.io/v1/transactions

# With additional options
curl --cert certificate.crt \
     --key private.key \
     --cacert ca.crt \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
     https://mtls.us.prd.caf.io/v1/transactions

# With data payload
curl --cert certificate.crt \
     --key private.key \
     --cacert ca.crt \
     -X POST \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
     -d '{"key1": "value1", "key2": "value2"}' \
     https://mtls.us.prd.caf.io/v1/transactions
```

{% hint style="info" %}
When using curl for testing, you may need to provide the full certificate chain using the `--cert` option or specify the certificate authority with `--cacert` if you're using a non-public CA.
{% endhint %}

{% hint style="info" %}
For more information about certificate validity, renewal, and management best practices, see [Managing Certificates](/caf-api/connect/authentication/certificates/managing-certificate.md).
{% endhint %}

## Troubleshooting `mTLS` connections

If you encounter issues with your `mTLS` connection, consider the following troubleshooting steps:

1. **Certificate Validation Failed**: Ensure your certificate is active and not expired or revoked.
2. **Private Key Issues**: Verify that your private key matches the certificate.
3. **Incorrect Certificate Format**: Make sure you're using the correct format for your language/framework.
4. **Certificate Issues**: Confirm your certificate is still valid and not revoked.
5. **Network Issues**: Check if there are any firewalls or proxies interfering with your `HTTPS` connection.

## Best practices

* **Keep certificates and private keys secure** in your application's deployment environment.
* Use **secure storage** for certificate files in your deployment environments.
* Implement **certificate rotation procedures** to handle certificate expiration.
* Set up **monitoring** for certificate expiration to avoid service interruptions.
* Follow the principle of **least privilege** when assigning permissions to services using `mTLS`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.caf.io/caf-api/connect/authentication/using-mtls.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
