## What is mTLS?

**mTLS (Mutual TLS)** is a security protocol where **both the client and server authenticate each other** using certificates, unlike regular TLS where only the server is authenticated.

## How it works

Socure provides a dedicated mTLS endpoint:

- **Base URL:** `https://mtls.riskos.socure.com`
- **Transport:** HTTPS with **mutual TLS (mTLS)**
- **Policy:** Client certificate is **required** – connections without a valid certificate are rejected at the load balancer.
- **Supported operations:** All [API Reference](https://help.socure.com/riskos/reference/postevaluation) endpoints are available through the mTLS base URL.

At this endpoint:

- The **External HTTPS Load Balancer**:

- Terminates TLS
  - Validates the client certificate against our configured **trust store**
- Allows only requests presenting a **valid client certificate issued from the agreed-upon client CA** to reach our services.
- Application authentication/authorization (for example, Bearer Auth Token, API keys) still enforced on top of mTLS

* * *

> 📘
>
> **Account-level constraints**:
>
> - **Account-Level Identity:** mTLS certificates are configured at the **Account level**, not per use case. All teams or applications within the same RiskOS™ account must use the same certificate bundle.
> - **Product Separation:** You **cannot** reuse mTLS certificates from Socure ID+. Because RiskOS™ is a separate account environment, a new certificate exchange specifically for RiskOS™ is required.
> - **Optional Usage:** mTLS is not strictly enforced for the entire account unless required by your internal policy.
>   
>   - **To use mTLS:** Call `https://mtls.riskos.socure.com`
>   - **To skip mTLS:** Call the standard endpoint `https://riskos.socure.com`

### Flow diagram

```
RiskOS™(HTTP)NEG(K8s endpoints)Backend ServiceURL MapTarget HTTPS Proxy+ ServerTlsPolicy+ TrustConfigForwarding Rule(Public IP:443)ClientRiskOS™(HTTP)NEG(K8s endpoints)Backend ServiceURL MapTarget HTTPS Proxy+ ServerTlsPolicy+ TrustConfigForwarding Rule(Public IP:443)ClientClient sendsclient certificate (mTLS)alt[Missing/Invalid client cert]alt[Valid client cert]Connect to https://mtls.riskos.socure.comForward TLS handshakeTLS + mTLS handshakeValidate client cert via TrustConfigclientValidationMode = REJECT_INVALIDTLS Handshake FailureConnection TerminatedMark request as mTLS-authenticatedSelect route based on host/pathRoute to Backend ServiceSelect endpointHTTP request (no TLS in-cluster)HTTP responseResponseResponseResponseEncrypted HTTPS responseResponse to clientmTLS (strict) – Client → External LB → K8s
```

## Prerequisites

Make sure the following are in place:

1. Ability to perform HTTPS requests with **client certificate authentication**.
2. Required certificate assets **unique to your RiskOS™ account**:

- A **client certificate** (client.crt).
   - Its **private key** (client.key).
   - The **client CA / chain** that issued that certificate.
3. Please share the Customer CA bundle (Root or Intermediates) with Socure for configuring in our Trust Store. The format should be as follows:

```undefined
-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----
```

## Certificate requirements

### 1. Client certificate type

- Must be an **X.509 certificate** suitable for TLS client authentication.
- Must be issued by a CA that we mutually agree on and configure in our **TrustConfig** as a **trustAnchor**.
- The certificate chain must be:
  - Client Leaf Cert → Intermediate(s) → Client Root CA

> 📘
>
> Note:
>
> The customer must provide a certificate authority (CA) certificate with Basic Constraints set to `CA:true`.

### 2. Subject / DN

We recommend:

- **Subject Common Name (CN):** A stable identifier we can associate with your system/tenant.
- Example:
  - `CN=partner-abc-prod-client`
- Optionally, **OU / O**:

- `OU=RiskOSIntegration, O=PartnerABC`

Socure maps certificate identity (CN / DN / serial / issuer) to your account on our side for future reference.

### 3. Key type and size

RSA 2048+ or ECDSA (P-256)

## How Socure configures trust on our side

You don't need to do this, but it helps you understand the behavior:

- We configure a **ServerTlsPolicy** on the Target HTTPS Proxy with:

- `clientValidationMode = REJECT_INVALID`
    
    → Any missing/invalid client certificate is rejected at TLS handshake

- `clientValidationTrustConfig` pointing to a **TrustConfig** that contains your **client CA** under `trustAnchors`

> **Implication for you:** If your client does not present a valid certificate signed by this CA, the TLS handshake fails before any HTTP request is received.

## Client-side configuration – general

From the client side, mTLS is simply:

- "Use this certificate + key when calling `https://mtls.riskos.socure.com`"

You typically configure:

- **Client certificate** file (PEM or PFX)
- **Private key** file (if not bundled)
- Trusted **server CA** (optional if our server certificate is from a public CA your system already trusts)

## Example integrations

### 1. cURL

cURL

```curl
curl -v \
  --cert /path/to/client.crt \
  --key /path/to/client.key \
  --cacert /path/to/ca_root.crt \
  https://mtls.riskos.socure.com/api/evaluation
  --header 'accept: application/json' \
  --header 'content-type: application/json'
  --data '
  {
    "data": {
      "individual": {
        .....
      },
      ....
    },
    ....
  }
```

**Notes:**

- `--cert`: Client certificate (PEM). If combined with key in PFX, use `--cert client.p12:password --cert-type P12`
- `--key`: Client private key
- `--cacert`: CA to verify our server certificate (optional if you already trust the issuing public CA)

If the certificate is missing or invalid, you see a TLS handshake error such as:

- `SSL_ERROR_HANDSHAKE_FAILURE_ALERT`
- `OPENSSL_internal:KEY_VALUES_MISMATCH`
- `Socket hang up`

### 2. Python as a client

Python

```python
import requests

BASE_URL = "https://mtls.riskos.socure.com"

# Paths to your certificate files
CLIENT_CERT = "/path/to/client.crt"      # client certificate (PEM)
CLIENT_KEY = "/path/to/client.key"       # client private key (PEM)
CA_CERT = "/path/to/ca_root.crt"         # CA to trust our server cert (optional if system trust is enough)

def main():
    try:
        # JSON payload matching your curl example
        payload = {
            "data": {
                "individual": {
                   ....
                },
                ....
            },
           ....
        }

headers = {
            "accept": "application/json",
            "content-type": "application/json",
        }

response = requests.post(
            f"{BASE_URL}/api/evaluation",
            headers=headers,
            json=payload,               # sends JSON body like curl --data '<json>'
            cert=(CLIENT_CERT, CLIENT_KEY),
            verify=CA_CERT,             # same as --cacert; use True if using system trust store
            timeout=10,
        )
        print("Status:", response.status_code)
        print("Body:", response.text)
    except requests.exceptions.SSLError as e:
        print("TLS/mTLS error:", e)
    except requests.exceptions.RequestException as e:
        print("Request error:", e)

if __name__ == "__main__":
    main()
```

## API behavior and authentication

Please note the following important points:

- **mTLS = transport-level identity**, not necessarily your full application authentication
- You must still provide:
  - Bearer token in `Authorization: Bearer YOUR_API_KEY`
  - Or API key header: `X-API-Key: YOUR_API_KEY`
- Typical pattern:
  - mTLS authenticates the **calling system**
  - Bearer token / API key authenticates the **user or client app context**

## Error scenarios you should expect

1. **TLS handshake failure (no HTTP status code)**
   - **Likely causes:**
     - Missing client certificate
     - Invalid chain (not signed by configured CA)
     - Expired or not yet valid certificate
   - **Resolution:**
     - Check your client certificate/key configuration
     - Check certificate validity dates
     - Confirm you're using the correct certificate for **production** vs **sandbox**
     - Confirm CA chain matches what you shared with us
2. **HTTP 401 / 403 / 429 from API**
   - mTLS succeeded, but:
     - Bearer token / API key is invalid or missing
     - Your IP is not whitelisted in our system
     - Your request hit the rate limit
3. **HTTP 404 / 405 / 500 responses**
   - mTLS layer is OK; these are regular API-level errors (wrong path, method, or internal error)

## Certificate rotation guidance

**Customer responsibilities:**

- Rotate customer certificates before the `not_after` date
- Notify us of the new customer CA (if your CA changes)

**Socure will:**

- Update our **TrustConfig** / trustAnchors if your CA changes
- Keep both old and new CAs during migration windows when needed

> **How to inform us:** Contact our Support team at [support@socure.com](mailto:support@socure.com).
>
> **Lead time required:** Please allow 3–5 business days for CA changes

## Common error messages and causes

Errors are often reported by the client's application, browser, or server logs during the TLS handshake.

- `SSL connect error`, `ERR_SSL_PROTOCOL_ERROR`, or `handshake failure`

These indicate a fundamental failure in the TLS negotiation process, often due to configuration issues on either the client or server side.

- `CERTIFICATE_VERIFY_FAILED` or `SSL certificate problem`

These errors are often seen in clients like Python requests or cURL and indicate a problem with the certificate itself or the validation process.

- `UNABLE_TO_GET_ISSUER_CERT` or `UNABLE_TO_VERIFY_LEAF_SIGNATURE`

This happens when the server (or client) cannot build a complete, trusted chain from the presented certificate back to a known and trusted root Certificate Authority (CA).

- `The user certificate is expired or blacklisted`

The validating party has identified that the certificate's validity date is in the past, or it is present on a Certificate Revocation List (CRL).

- `Unsupported certificate purpose` or `client_cert_chain_invalid_eku`

The client certificate does not have the required Extended Key Usage (EKU) attribute (specifically "Client Authentication") to be used for mTLS.

- `No client certificate presented` or `client_cert_not_provided`

The client did not send a certificate when the server requested one during the handshake.

- `client_cert_invalid_rsa_key_size` or `client_cert_unsupported_elliptic_curve_key`

The certificate uses an algorithm or key size that is not supported by the validating system.

- `hostname mismatch`

The hostname in the server's certificate does not match the domain name the client is trying to connect to.
