ClearBlade IoT Enterprise and Edge

Mutual TLS - mTLS

In normal TLS, when a client connects to a server the server presents a SERVER certificate to the client. The client then verifies the server certificate. Once verified an encrypted connection is established.

In mTLS (Mutual TLS), after the client successfully verifies the server it then presents its own CLIENT certificate to the server. The server then verifies the client certificate. Once verified an encrypted connection is established.

mTLS is used to prevent unauthorized clients from accessing services even if they know the server's URL/port. mTLS is more secure than using API keys or tokens alone because those are passed in headers and could be stolen and reused.

Version note: this page describes ClearBlade IoT Enterprise 2026.2.6 and newer. Currently mTLS trust is per system: a device certificate is accepted only if it was signed by a CA registered on the system the device connects to. If you are upgrading from an older release, see Upgrading from a release before 2026.2.6.

How verification works

When a device connects over mTLS the platform:

  1. Accepts any client certificate during the TLS handshake. Nothing is verified yet, because the target system is not known until the device authenticates.

  2. Determines the system: from the MQTT CONNECT password (system key or system alias), or for HTTP from the URL, the ClearBlade-SystemKey header, or a certificate CN of the form system_key:SYSTEM_KEY.

  3. Verifies that the device certificate was signed by one of that system's mTLS roots. The device certificate must allow client authentication (Extended Key Usage clientAuth, or no EKU at all).

  4. Rejects the certificate if the system is disabled, if the system has no mTLS roots, or if the device certificate is revoked for that system.

  5. Optionally checks that the device name matches the certificate CN (see Device name and the certificate CN).

A successful verification is cached per connection. Revocation is checked on every request.

Terms

  1. SYSTEM ROOT certificate:
    A CA certificate registered on one system. Device certificates signed by it are trusted for that system only. This is the certificate that controls who can connect. Any developer with access to the system can manage its system roots.

  2. DEVICE certificate:
    A device-specific client certificate, signed directly by a system root.

Setting up mTLS for a system

  1. Create a CA (private key and self-signed CA certificate) with your own tooling. The CA certificate must have Basic Constraints CA:TRUE, a key usage that allows certificate signing, and must not be expired.

  2. Register the CA certificate on the system: Add System Root (below).

  3. Sign each device certificate with that CA, with Extended Key Usage clientAuth. Put the device name in the CN (see Device name and the certificate CN).

  4. Connect the device (see Device authentication).

The CA private key never needs to be sent to the platform.

Upgrading from a release before 2026.2.6

Before 2026.2.6, device CAs were registered once for the whole platform, by an admin. Those registrations are not copied to systems automatically, so devices are refused until their CA is registered on their system. Either register the CA on each system with Add System Root, or ask a platform admin to run the subcommand to migrate mtls-roots with a system key (or with * for all systems). Use * with care: it gives every system trust in every previously registered CA.

Revoked certificates are not migrated. Revoke them again per system (see Revoking certificates).


Managing System Root Certificates

System roots decide which client certificates a system trusts. Any developer with access to the system can manage them.

List System Roots
GET {URL}/api/v/1/mtls-certs/roots/{system_key}

Header Parameters


ClearBlade-DevToken

string; developer token

Response body JSON representation

[ { "name": <string>, "certificate": <string; PEM>, "subject": <string>, "not_before": <RFC3339 time>, "not_after": <RFC3339 time>, "sha256_fingerprint": <string; hex>, "upload_time": <RFC3339 time>, "spki_sha256": <string; hex SHA-256 of the public key> }, ... ]

Results are sorted by name.

Add System Root
POST {URL}/api/v/1/mtls-certs/roots/{system_key}/{root_name}

Header Parameters


ClearBlade-DevToken

string; developer token

Request body JSON representation

{ "certificate": <string; exactly one PEM certificate> }

Response Code

Meaning

200

Success. Returns the root in the same format as List System Roots.

  • root_name is 1 to 128 characters, starts with a letter or digit, and contains only letters, digits, ".", "_" or "-".

  • The certificate must be a CA (Basic Constraints CA:TRUE), must allow certificate signing if it has a key usage, and must not be expired.

  • Only the certificate is stored. Do not send a private key.

  • This call does not replace an existing root with the same name. To replace a root, delete it first.

Delete System Root
DELETE {URL}/api/v/1/mtls-certs/roots/{system_key}/{root_name}

Header Parameters


ClearBlade-DevToken

string; developer token

Response Code

Meaning

200

Success


Revoking Certificates

Revocations are per system. A revoked device certificate is identified by the public key hash of the system root that signed it, and its serial number.

  • issuer_spki_sha256: the spki_sha256 of the system root that signed the device certificate, from List System Roots (lowercase hex SHA-256 of the root's DER-encoded public key).

  • serial_number: the revoked certificate's serial number in hex. Colons are allowed and case is ignored.

List Revoked Certificates
GET {URL}/api/v/1/mtls-certs/revoked/{system_key}

Header Parameters


ClearBlade-DevToken

string; developer token

Query Parameters


page

integer; optional, default 1

page_size

integer; optional, default and maximum 1000

issuer_spki_sha256

string; optional filter

Response body JSON representation

{ "total": <integer>, "revocations": [ { "issuer_spki_sha256": <string>, "serial_number": <string>, "revocation_time": <RFC3339 time>, "reason_code": <integer or null>, "description": <string> }, ... ] }

Revoke Certificate
PUT {URL}/api/v/1/mtls-certs/revoked/{system_key}

Header Parameters


ClearBlade-DevToken

string; developer token

Request body JSON representation

{ "serial_number": <string; required>, "issuer_spki_sha256": <string; required>, "reason_code": <integer; optional, RFC 5280 reason code>, "description": <string; optional> }

Response Code

Meaning

200

Success. Returns the stored revocation entry.

Un-revoke Certificate
DELETE {URL}/api/v/1/mtls-certs/revoked/{system_key}?issuer_spki_sha256={hash}&serial_number={serial}

Header Parameters


ClearBlade-DevToken

string; developer token

Response Code

Meaning

200

Success

Both query parameters are required.

Disabling or deleting a device does not stop it from authenticating over mTLS. To cut off a device, revoke its certificate.


Device Name and the Certificate CN

The platform reads the device name from the device certificate's CN:

  • If the CN matches the pattern device_name:NAME (configurable with Security.MTLSCertDeviceNamePattern), NAME is the device name.

  • Otherwise the whole CN is the device name, unless the CN only names a system (system_key:KEY).

When the platform setting Security.CheckCertificateCNForMTLS is on, the device name the client sends must equal the name in the CN, or authentication fails. Check how your environment has it configured.


Device Authentication (MQTT)

Devices authenticating over mTLS must:

  1. Connect to the mTLS host and port. On ClearBlade-hosted environments this is port 444. The platform itself listens on Http.HttpMTLSPort (default 9001), only when Security.EnableMutualTLSAuth is on.

  2. Set the TLS ALPN protocol to clearblade_mqtt_mtls. Without it the connection is treated as HTTP.

  3. Present the device certificate and use the matching private key.

  4. Send MQTT CONNECT with:

    • username: a stringified JSON object with item name set to the device name, for example {"name": "yourDeviceName"}.

    • password: the system key or a system alias. This identifies the system; it is not a secret.

If the device does not exist yet, the platform creates it on first connect (except for IoT Core clients).

Examples:

  1. Using the ClearBlade Python SDK: search for 'mTLS' in the README.

  2. Using paho.mqtt.python (1.x API):

Python
import paho.mqtt.client as mqtt
import ssl

ca_certs  = "/path/to/issuer/of/environment/cert/DigiCertGlobalRootCA.crt.pem"
cert_file = "/path/to/clientCert.pem"
key_file  = "/path/to/clientPrivateKey.pem"

mqtt_bridge_hostname = "your.environment.com"
mqtt_bridge_port = 444

ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=ca_certs)
ssl_context.load_cert_chain(certfile=cert_file, keyfile=key_file)
ssl_context.set_alpn_protocols(["clearblade_mqtt_mtls"])

client = mqtt.Client(client_id='anyClientID')
client.username_pw_set(username='{"name": "yourDeviceName"}', password='yourSystemKey')
client.tls_set_context(ssl_context)
def on_connect(client, userdata, flags, rc):
    print("Connected:", mqtt.connack_string(rc))
    client.subscribe("yourMqttTopic", qos=1)

def on_message(client, userdata, message):
    print("Received '{}' on topic '{}'".format(message.payload.decode(), message.topic))

client.on_connect = on_connect
client.on_message = on_message

client.connect(mqtt_bridge_hostname, mqtt_bridge_port, keepalive=1500)
client.loop_forever()

Note the following in this example:

  1. ca_certs is the CA that issued the ENVIRONMENT's server certificate, normally a well-known public CA (e.g. DigiCert Global Root CA, Let's Encrypt). It is not your device CA.

  2. cert_file is the device certificate.

  3. key_file is the device's private key.

  4. username must be a stringified JSON object with item name set to the device name.

  5. password must be the system key or a system alias.

If authentication fails, the TLS handshake still succeeds and the broker returns a CONNACK with a not-authorized code.


HTTP Requests Using mTLS

Normally HTTP requests to ClearBlade systems must include a token header for a DEVELOPER, USER or DEVICE with the appropriate permissions:

  • ClearBlade-DevToken

  • ClearBlade-UserToken

  • ClearBlade-DeviceToken

On an environment with mTLS enabled, a device can instead send the request over the mTLS port with its certificate and no token. The request runs as that device.

  • System: taken from the URL if it contains a system key, otherwise from the ClearBlade-SystemKey header, otherwise from a certificate CN of the form system_key:SYSTEM_KEY. A system alias can be used in place of a key.

  • Device: taken from the device certificate CN (see Device name and the certificate CN). If Security.CheckCertificateCNForMTLS is off, a ClearBlade-DeviceName header can be used instead.

For example, to call a code service with curl, send a POST to https://your.environment.com:444/api/v/1/code/YOUR_SYSTEM_KEY/myCodeService and pass the device certificate with the --cert option, the device key with the --key option, and the CA of the SERVER's certificate with the --cacert option.

Get a Device Token over mTLS
POST {URL}/api/v/4/devices/mtls/auth

Must be sent over the mTLS port with the device certificate.

Header Parameters


ClearBlade-SystemKey

string; system key or alias (unless the certificate CN names the system)

Request body JSON representation

{ "name": <string; device name>, "system_key": <string; optional, must match the verified system> }

Returns a device token. If the device does not exist it is created.


Platform Configuration

Setting

Default

Meaning

Security.EnableMutualTLSAuth

false

Turns on the mTLS listener

Http.HttpMTLSPort

:9001

mTLS listen port. ClearBlade-hosted environments expose it as 444

Security.MTLSMQTTALPN

clearblade_mqtt_mtls

ALPN protocol that routes an mTLS connection to the MQTT broker

Security.CheckCertificateCNForMTLS

see note

Require the device name to match the certificate CN. The built-in default and the sample config disagree, so check your environment

Security.MTLSCertDeviceNamePattern

device_name:([^;]+)

Regex to extract the device name from a CN

Security.MTLSCertSystemKeyPattern

system_key:([^;]+)

Regex to extract the system key from a CN

Security.MTLSCacheMaxSystems

1000

Systems whose roots and revocations each node caches

Security.MTLSRevocationCacheSizePerSystem

10000

Revocation entries each node caches per system