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

# mTLS Client Certificates

> Secure API communication with mutual TLS (mTLS) client certificates. Store and manage certificates for banking APIs, government services, and enterprise systems.

# mTLS Client Certificates

Many high-security APIs require **mutual TLS (mTLS)** authentication where both the client and server present certificates to verify identity. KnoxCall supports storing client certificates as secrets and automatically using them for API requests.

## What is mTLS?

**Standard TLS (HTTPS):**

```text theme={"dark"}
Client → Server: "Hello"
Server → Client: "Here's my certificate"
Client: Verifies server certificate ✅
Connection established
```

**Mutual TLS (mTLS):**

```text theme={"dark"}
Client → Server: "Hello"
Server → Client: "Here's my certificate"
Client: Verifies server certificate ✅
Server → Client: "Now show me YOUR certificate"
Client → Server: "Here's my client certificate"
Server: Verifies client certificate ✅
Connection established
```

### When to Use mTLS

**Common use cases:**

* 🏦 **Banking APIs** (PSD2, Open Banking)
* 🏛️ **Government services** (IRS, HMRC, tax authorities)
* 🏢 **Enterprise B2B APIs** (high-security partners)
* 💳 **Payment processors** (some card networks)
* 🔐 **Zero-trust architectures** (service mesh, internal APIs)

**Example providers requiring mTLS:**

* Plaid (some endpoints)
* TrueLayer (Open Banking)
* Yodlee
* UK HMRC APIs
* German Tax Authority APIs
* Some AWS services

## Certificate Formats

### Supported Formats

KnoxCall accepts certificates in **PEM format** (text-based):

```pem theme={"dark"}
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKJ5cqZ3xj8VMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
... (more lines) ...
-----END CERTIFICATE-----

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7VJTUt9Us8cKj
MzEfYyjiWA4R4/M2bS1+fWIcPm15j9zB/2cdY9SZ4O4nM4F4SfbmA9aM8jl3qv8E
... (more lines) ...
-----END PRIVATE KEY-----
```

### Certificate Components

A complete mTLS setup includes:

1. **Client Certificate** (`cert.pem`)
   * Proves your identity to the server
   * Signed by a Certificate Authority (CA)
   * Contains public key

2. **Private Key** (`key.pem`)
   * Paired with certificate
   * Kept secret (never share!)
   * Used to sign requests

3. **Passphrase** (optional)
   * Protects the private key
   * Required if key is encrypted
   * Stored encrypted in KnoxCall

4. **CA Certificate** (optional)
   * Verifies server's certificate
   * Usually not needed (uses system trust store)

### Format Conversion

If your certificate is in a different format:

**From PKCS#12 (.pfx, .p12) to PEM:**

```bash theme={"dark"}
# Extract certificate
openssl pkcs12 -in cert.pfx -clcerts -nokeys -out cert.pem

# Extract private key
openssl pkcs12 -in cert.pfx -nocerts -out key.pem

# Remove passphrase (optional)
openssl rsa -in key.pem -out key-nopass.pem
```

**From DER to PEM:**

```bash theme={"dark"}
# Convert certificate
openssl x509 -inform DER -in cert.der -out cert.pem

# Convert key
openssl rsa -inform DER -in key.der -out key.pem
```

**Combine certificate and key:**

```bash theme={"dark"}
cat cert.pem key.pem > combined.pem
```

## Creating a Certificate Secret

### Step 1: Prepare Your Certificate

Combine your certificate and private key into a single file:

```bash theme={"dark"}
# combined.pem
-----BEGIN CERTIFICATE-----
... your certificate ...
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
... your private key ...
-----END PRIVATE KEY-----
```

**Important:**

* Certificate must come first
* Private key must come second
* Include the `-----BEGIN/END-----` markers
* No extra spaces or characters

### Step 2: Create Secret in KnoxCall

1. Navigate to **Secrets** → **Create Secret**
2. Fill in details:

```yaml theme={"dark"}
Name: bank_api_certificate
Type: Certificate (mTLS)
Description: Client certificate for Bank XYZ API
```

3. **Upload certificate:**
   * Paste combined PEM content (cert + key)
   * Or upload `.pem` file

4. **Optional: Add passphrase**
   * If your private key is encrypted
   * Enter passphrase (stored encrypted)

5. Click **Create**

### Step 3: Verify Certificate

After creation, KnoxCall shows:

```text theme={"dark"}
✅ Certificate validated
📜 Subject: CN=YourCompany, O=YourOrg, C=US
📅 Valid from: 2024-01-01
📅 Expires: 2026-01-01
🔑 Private key: Present
🔐 Passphrase: Yes (encrypted)
```

## Using Certificates in Routes

### Basic Usage

Reference the certificate in your route's advanced configuration:

**Route Configuration:**

```json theme={"dark"}
{
  "certificate_secret_id": "{{secret:bank_api_certificate}}"
}
```

KnoxCall automatically:

* Loads the certificate and private key
* Decrypts the passphrase if present
* Creates mTLS agent for the request
* Presents certificate during TLS handshake

### With OAuth2

Some APIs require **both** OAuth2 and mTLS:

```json theme={"dark"}
{
  "oauth2_secret_id": "{{secret:bank_oauth}}",
  "certificate_secret_id": "{{secret:bank_api_certificate}}"
}
```

Flow:

1. KnoxCall performs OAuth2 token exchange (with mTLS if provider requires it)
2. Subsequent API requests use both OAuth2 token **and** mTLS certificate

### Environment-Specific Certificates

Use different certificates for production vs sandbox:

**Create certificate secret:**

```text theme={"dark"}
Secret: bank_api_certificate

Environments:
  production:
    cert: -----BEGIN CERTIFICATE----- (prod cert)
    key: -----BEGIN PRIVATE KEY----- (prod key)
    passphrase: prod-passphrase

  sandbox:
    cert: -----BEGIN CERTIFICATE----- (sandbox cert)
    key: -----BEGIN PRIVATE KEY----- (sandbox key)
    passphrase: sandbox-passphrase
```

**Route configuration (same for all environments):**

```json theme={"dark"}
{
  "certificate_secret_id": "{{secret:bank_api_certificate}}"
}
```

* Production route → uses production certificate
* Sandbox route → uses sandbox certificate
* Hard fail if environment missing

## Real-World Examples

### Example 1: Open Banking (TrueLayer)

**Requirement:** PSD2-compliant Open Banking requires eIDAS certificates

**Setup:**

```bash theme={"dark"}
# You receive from CA:
- transport_cert.pem (eIDAS transport certificate)
- transport_key.pem (private key)

# Combine:
cat transport_cert.pem transport_key.pem > truelayer_mtls.pem
```

**Create secret:**

```text theme={"dark"}
Name: truelayer_mtls_cert
Type: Certificate
Content: (paste truelayer_mtls.pem)
```

**Route config:**

```json theme={"dark"}
{
  "target_url": "https://api.truelayer.com",
  "certificate_secret_id": "{{secret:truelayer_mtls_cert}}",
  "oauth2_secret_id": "{{secret:truelayer_oauth}}"
}
```

### Example 2: Bank XYZ Direct API

**Requirement:** Corporate banking API with mTLS only (no OAuth2)

**Create secret:**

```text theme={"dark"}
Name: bankxyz_client_cert
Type: Certificate
Content:
  -----BEGIN CERTIFICATE-----
  ... (client cert) ...
  -----END CERTIFICATE-----
  -----BEGIN ENCRYPTED PRIVATE KEY-----
  ... (encrypted key) ...
  -----END ENCRYPTED PRIVATE KEY-----
Passphrase: your-key-passphrase
```

**Route config:**

```json theme={"dark"}
{
  "target_url": "https://api.bankxyz.com",
  "certificate_secret_id": "{{secret:bankxyz_client_cert}}",
  "headers": {
    "API-Key": "{{secret:bankxyz_api_key}}"
  }
}
```

### Example 3: Government Tax API

**Requirement:** HMRC API requires mTLS + OAuth2 + API key

**Secrets:**

```text theme={"dark"}
1. hmrc_mtls_cert (Certificate type)
2. hmrc_oauth (OAuth2 type)
3. hmrc_vendor_key (String type)
```

**Route config:**

```json theme={"dark"}
{
  "target_url": "https://api.service.hmrc.gov.uk",
  "certificate_secret_id": "{{secret:hmrc_mtls_cert}}",
  "oauth2_secret_id": "{{secret:hmrc_oauth}}",
  "headers": {
    "Gov-Vendor-Version": "1.0",
    "Gov-Vendor-Public-Key": "{{secret:hmrc_vendor_key}}"
  }
}
```

## Security Best Practices

### ✅ Do This

1. **Use passphrase-protected keys**
   * Extra layer of security
   * Prevents key theft if certificate leaked

2. **Set certificate expiry reminders**
   * Certificates expire (typically 1-2 years)
   * Set calendar reminder 30 days before expiry

3. **Store backups securely**
   * Keep original `.pfx` or `.p12` file in secure vault
   * Don't email certificates

4. **Use environment-specific certificates**
   * Separate certificates for prod/sandbox
   * Prevents accidental production API usage in dev

5. **Revoke old certificates**
   * When renewing, revoke old certificate with CA
   * Remove from KnoxCall after grace period

### ❌ Avoid This

1. **Don't share private keys**
   * Each system should have unique certificate
   * Never email or commit to git

2. **Don't use unencrypted keys**
   * Always use passphrase-protected keys
   * Even if "just for testing"

3. **Don't ignore expiry warnings**
   * Expired certificate = API downtime
   * Plan renewal 60 days ahead

4. **Don't hardcode passphrases**
   * Use KnoxCall's encrypted passphrase field
   * Not environment variables

## Certificate Management

### Checking Expiry

View expiry in secret detail page:

```text theme={"dark"}
Certificate: bank_api_certificate
├─ Subject: CN=YourCompany
├─ Issuer: CN=Certificate Authority
├─ Valid from: 2024-01-01 00:00:00 UTC
├─ Expires: 2026-01-01 00:00:00 UTC
├─ Days remaining: 347
└─ Status: ✅ Valid
```

**Expiry warnings:**

* 90 days: 🟡 Warning (plan renewal)
* 30 days: 🟠 Urgent (renew now)
* Expired: 🔴 Invalid (API calls will fail)

### Renewing Certificates

**Process:**

1. **Obtain new certificate** from CA
2. **Create new secret** with different name:
   ```text theme={"dark"}
   Old: bank_api_certificate
   New: bank_api_certificate_2025
   ```
3. **Test in sandbox** first
4. **Update routes** to use new secret:
   ```json theme={"dark"}
   {
     "certificate_secret_id": "{{secret:bank_api_certificate_2025}}"
   }
   ```
5. **Deploy to production**
6. **Monitor** for 48 hours
7. **Delete old secret** after grace period

**Zero-downtime renewal:**

* Old certificate valid until expiry
* New certificate active before expiry
* Update routes during low-traffic period

### Rotating Certificates

**When to rotate:**

* Scheduled renewal (before expiry)
* Security incident (suspected compromise)
* Compliance requirement (quarterly rotation)
* Organization change (company rename)

**Rotation checklist:**

* [ ] Generate new CSR (Certificate Signing Request)
* [ ] Submit to CA
* [ ] Receive and validate new certificate
* [ ] Upload to KnoxCall as new secret
* [ ] Test in sandbox environment
* [ ] Update production routes
* [ ] Monitor API calls for 48 hours
* [ ] Revoke old certificate with CA
* [ ] Delete old secret from KnoxCall

## Troubleshooting

### "Certificate validation failed"

**Problem:** KnoxCall rejects your certificate during upload

**Common causes:**

1. **Incorrect format**
   ```text theme={"dark"}
   ❌ Wrong: binary .pfx file
   ✅ Right: PEM text format
   ```

2. **Missing private key**
   ```text theme={"dark"}
   ❌ Wrong: only certificate, no key
   ✅ Right: certificate + private key
   ```

3. **Mismatched cert and key**
   ```text theme={"dark"}
   Cert and key don't form a pair
   → Ensure they were generated together
   ```

4. **Expired certificate**
   ```text theme={"dark"}
   Certificate already expired
   → Check expiry date before upload
   ```

**Solution:**

```bash theme={"dark"}
# Verify certificate
openssl x509 -in cert.pem -text -noout

# Verify key
openssl rsa -in key.pem -check

# Verify they match
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in key.pem | openssl md5
# (hashes should match)
```

### "mTLS handshake failed"

**Problem:** API request fails with TLS error

**Possible causes:**

1. **Wrong certificate uploaded**
   * Production cert used in sandbox (or vice versa)
   * Solution: Check environment-specific values

2. **Passphrase incorrect**
   * Private key is encrypted but passphrase wrong
   * Solution: Re-upload with correct passphrase

3. **Server doesn't trust your certificate**
   * Certificate not from approved CA
   * Solution: Obtain certificate from API provider's required CA

4. **Certificate expired**
   * Check expiry in secret detail page
   * Solution: Renew certificate

5. **Hostname mismatch**
   * Certificate's CN doesn't match request hostname
   * Solution: Obtain cert with correct subject name

**Debug steps:**

```bash theme={"dark"}
# Test mTLS locally
curl --cert cert.pem \
     --key key.pem \
     https://api.example.com/test

# If it works locally but fails in KnoxCall:
# → Check passphrase, environment config
```

### "Cannot decrypt private key"

**Problem:** KnoxCall can't load your certificate for requests

**Causes:**

1. **Passphrase wrong or missing**
   * Encrypted key needs passphrase
   * Solution: Update secret with correct passphrase

2. **Corrupted key**
   * Key data damaged during upload
   * Solution: Re-upload certificate

3. **Unsupported encryption**
   * Very old key encryption algorithms
   * Solution: Re-encrypt key with modern algorithm:
     ```bash theme={"dark"}
     openssl rsa -in old_key.pem -out new_key.pem
     ```

### "Private key not found in secret"

**Problem:** Certificate uploaded but key missing

**Solution:**

Ensure your PEM file contains both:

```pem theme={"dark"}
-----BEGIN CERTIFICATE-----
... certificate ...
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----  ← Must be present!
... private key ...
-----END PRIVATE KEY-----
```

If you have them separately:

```bash theme={"dark"}
cat cert.pem key.pem > combined.pem
# Then upload combined.pem
```

## Advanced Configuration

### Custom CA Certificates

If the API server uses a custom CA:

```json theme={"dark"}
{
  "certificate_secret_id": "{{secret:client_cert}}",
  "ca_bundle_secret_id": "{{secret:custom_ca_bundle}}"
}
```

Create `custom_ca_bundle` secret (String type):

```pem theme={"dark"}
-----BEGIN CERTIFICATE-----
... CA certificate ...
-----END CERTIFICATE-----
```

### SNI (Server Name Indication)

For servers requiring specific SNI:

```json theme={"dark"}
{
  "certificate_secret_id": "{{secret:client_cert}}",
  "tls_servername": "api.specific-domain.com"
}
```

### Disabling Certificate Verification (NOT RECOMMENDED)

For testing only (never in production):

```json theme={"dark"}
{
  "certificate_secret_id": "{{secret:client_cert}}",
  "tls_reject_unauthorized": false
}
```

⚠️ **Warning:** This disables server certificate validation and makes you vulnerable to man-in-the-middle attacks. Only use in isolated test environments.

## Compliance & Auditing

### Audit Trail

All certificate create/update/delete operations are captured in the audit log. Query them via:

```bash theme={"dark"}
curl "https://api.knoxcall.com/v1/audit-logs?resource_type=secret" \
  -H "Authorization: Bearer tk_live_..."
```

Each entry includes `action` (`create`, `update`, `delete`), `resource_id` (the secret ID), and the source `ip_address`.

### Compliance Requirements

**PCI DSS:**

* ✅ Certificates encrypted at rest
* ✅ Private keys never logged
* ✅ Access audit trail
* ✅ Expiry monitoring

**SOC 2:**

* ✅ Certificate lifecycle management
* ✅ Change tracking
* ✅ Access controls
* ✅ Secure deletion

**PSD2 (Open Banking):**

* ✅ eIDAS certificate support
* ✅ Qualified signature certificates
* ✅ Environment segregation

## API Reference

### Create Certificate Secret

```http theme={"dark"}
POST /v1/secrets/certificate
Authorization: Bearer tk_live_...
Content-Type: application/json

{
  "name": "client_certificate",
  "certificate_content": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
  "passphrase": "optional-key-passphrase",
  "certificate_type": "pem"
}
```

Field `certificate_type` defaults to `pem`. Accepted values: `pem`, `pfx`, `p12`, `crt`, `cer`, `key`, `pkcs7`, `p7b`, `p7c`.

### Update Certificate Value (Environment-Specific)

Update an existing certificate's value for a specific environment:

```http theme={"dark"}
PUT /v1/secrets/{id}/value?environment=staging
Authorization: Bearer tk_live_...
Content-Type: application/json

{
  "value": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
}
```

### Get Certificate Info (value never returned)

```http theme={"dark"}
GET /v1/secrets/{id}
Authorization: Bearer tk_live_...

Response:
{
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "CLIENT_CERTIFICATE",
    "secret_type": "certificate",
    "base_environment": "production",
    "collection_id": null,
    "created_at": "2025-01-15T10:00:00.000Z",
    "expires_at": null,
    "environment_count": 1
  },
  "meta": { "request_id": "..." }
}
```

See the [Secrets API reference](/api-reference/secrets) for the full endpoint reference.

## Next Steps

<CardGroup cols={2}>
  <Card title="OAuth2 + mTLS" icon="lock" href="/security/oauth2-flow">
    Combine OAuth2 with mTLS authentication
  </Card>

  <Card title="Secret Management" icon="key" href="/essentials/secrets/secrets-overview">
    Learn about secret types and management
  </Card>

  <Card title="Environment Secrets" icon="layer-group" href="/essentials/secrets/environment-specific-secrets">
    Use different certificates per environment
  </Card>

  <Card title="Certificate Rotation" icon="rotate" href="/security/rotation-strategies">
    Best practices for certificate renewal
  </Card>
</CardGroup>

***

<CardGroup cols={2}>
  <Card title="📊 Guide Info" icon="info-circle">
    * **Level**: Advanced
    * **Time**: 20 minutes
    * **Prerequisites**: Understanding of PKI and TLS
  </Card>

  <Card title="🏷️ Tags" icon="tags">
    `mtls`, `certificates`, `security`, `pki`, `banking`, `authentication`
  </Card>
</CardGroup>
