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:
-
Accepts any client certificate during the TLS handshake. Nothing is verified yet, because the target system is not known until the device authenticates.
-
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.
-
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).
-
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.
-
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
-
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. -
DEVICE certificate:
A device-specific client certificate, signed directly by a system root.
Setting up mTLS for a system
-
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.
-
Register the CA certificate on the system: Add System Root (below).
-
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).
-
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 |
|---|
|
|
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 |
|---|
|
|
|
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 |
|---|
|
|
Revoke Certificate
PUT {URL}/api/v/1/mtls-certs/revoked/{system_key}
|
Header Parameters |
|
|---|---|
|
ClearBlade-DevToken |
string; developer token |
|
Request body JSON representation |
|---|
|
|
|
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:
-
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.
-
Set the TLS ALPN protocol to clearblade_mqtt_mtls. Without it the connection is treated as HTTP.
-
Present the device certificate and use the matching private key.
-
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:
-
Using the ClearBlade Python SDK: search for 'mTLS' in the README.
-
Using paho.mqtt.python (1.x API):
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:
-
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.
-
cert_file is the device certificate.
-
key_file is the device's private key.
-
username must be a stringified JSON object with item name set to the device name.
-
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 |
|---|
|
|
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 |