ClearBlade IoT Enterprise supports various types of authentication.

Active key authentication

A ClearBlade user token is required to communicate with a broker. A token can be obtained via a REST endpoint call or MQTT.

Connect

Required keys

Description

Example values

URL

<PLATFORM_IP>

https://platform.clearblade.com/

Port

<PORT_NUMBER>

8905

Username

<SYSTEM_KEY>

bacb8fb60bb4d7c2c2c0e4bb9701

Password

<SYSTEM_SECRET>

BACB8FB60BFDDB7DB97D7A8BF01

ClientId

<USER_EMAIL>:<PASSWORD> for User, <DEVICE_NAME>:<ACTIVE_KEY> for devices

cbman@clearblade.com:cl34r8l4d3 or temperature-sensor:faqb8fb60bc2c2b1c0e4bb9701

TLS (optional)

<ALLOW_TLS>

true

Subscribe

Extract token

Block mapping in the above packet structure:

Block-Num

Description

1

Token length

2

Token

3

User ID or device name length

4

User ID or device name

5

Messaging URL length

6

Messaging URL

Once the client is authenticated, the token can be extracted, and the connection can be established.

Error codes

Referring to MQTT 3.1.1 spec

Value

Return code response

Description

0

0x00 Connection Accepted

Connection accepted

1

0x01 Connection Refused, unacceptable protocol version

The server does not support the MQTT protocol level requested by the client

2

0x02 Connection Refused, identifier rejected

The client identifier is correct (UTF-8) but unallowed by the server. A duplicate clientid can cause this

3

0x03 Connection Refused, Server unavailable

The network connection has been made, but the MQTT service is unavailable

4

0x04 Connection Refused, bad user name or password

The data in the user name or password is malformed

5

0x05 Connection Refused, not authorized

The client is not authorized to connect. For example, entering the incorrect password

6-255

Reserved for future use



Public key (asymmetric) authentication

A device must create a private/public key pair. The private key is only left local on the device, while the public key is uploaded to the ClearBlade IoT Enterprise system’s device record.

See Creating key pairs to create the key pair.

To authenticate, the device will construct a JSON Web Token (JWT) based on the private key and present that on the MQTT authentication or REST endpoint’s connect packet. The JWT is used in place of the standard ClearBlade auth token.


To add the public key to the device, use the following steps and example images:

  1. Find the device in the system’s device table:

    image-20240206-171618.png

  2. Right-click the device’s gear icon and choose Public Keys, then click the Add button:

  3. Pick the appropriate key format:

    ClearBlade IoT Core supports the RSA and elliptic curve algorithms. For details on key formats, see Public key format.

Claims

ClearBlade IoT Enterprise requires these reserved claim fields. They may appear in any order in the claim set.

Name

Description

Required for

iat

Issued at: The timestamp when the token was created, specified as seconds since 00:00:00 UTC, January 1, 1970. The server may report an error if this timestamp is too far in the past or future (allowing 10 minutes for skew).

MQTT, HTTP

exp

Expiration: The timestamp when the token stops being valid, specified as seconds since 00:00:00 UTC, January 1, 1970. The token’s maximum lifetime is 24 hours + skew.

  • The server will close all MQTT connections a few seconds after the token expires (allowing for skew) because MQTT cannot refresh credentials. A new token must be minted to reconnect. Because of the allowed skew, the token’s minimum lifetime will be equal to the acceptable clock skew.

  • Each HTTP request must include a JWT, regardless of expiration time.

  • Clients in Network Time Protocol (NTP) capable devices can use the Google Public NTP Server to keep the device clock synchronized; the authentication requirement is to keep the clock synchronized with an up to 10-minute skew.

MQTT, HTTP

sk

System key: This must be a single string containing the ClearBlade registry’s system key. This can be obtained by clicking the API keys button at the top-right of the ClearBlade Registry Details page.

MQTT, HTTP

uid

User ID: This must be a single string containing the deviceId.

MQTT, HTTP

ut

User type: This must be an integer hard-coded to value 3.

MQTT, HTTP

The optional nbf(not before) claim will be ignored.

A JSON representation of the required reserved fields in a ClearBlade IoT Core JWT claim set is shown below:

{
  "aud": "my-project",
  "iat": 1509654401,
  "exp": 1612893233
}

Only devices will be supported with this method.

Client type

Client ID

Username field

Password field

New ClearBlade client via JWT

Anything

-unused-

JWT token with sk, uid, and ut claims

Each time the client sends an MQTT message (including PINGREQ), the ClearBlade MQTT Broker checks the exp. If the current time is later than exp + 10m then the client will disconnected. The 10 minutes is to allow for time skew between client and server.

The Python file shows an example of generating a JWT for the MQTT client’s password.



mTLS

Devices may connect using an mTLS approach to gain their access token. ClearBlade handles mTLS auth and TLS termination.

The mTLS configuration will be valid for all systems running in the IoT Enterprise instance.

Currently, no user interface administration is available to manage the loaded certificates. All certificates must be loaded to the server via API calls.

Requirements

The device name must be the cn (common name) in the cert presented. The platform verifies that the certificate passed in is for the device.

APIs

/admin/settings/mtls

GET, PUT (upsert), and DELETE support. Admin only.

PUT:

Body required:

{"root_ca": "certificate in PEM format. <required>", "crl": "certificate revocation list in PEM format. <optional>"}

Returns nil on success

GET:

No query support. Get the latest mTLS settings in JSON:

{"root_ca": "certificate in PEM format", "crl": "certificate revocation list in PEM format"}

DELETE:

No query support. Deletes mTLS settings.

/admin/revoked_certs

GET, POST, and DELETE support. Admin only.

POST:

Use to revoke a certificate. Body required:

{
“certificate_hash”: "sha256 hash of the ASN.1 DER format of the certificate <required>",
"description": <optional>
}

Returns nil on success.

GET:

Query supported. An empty query gets all revoked certificates, including those that match the query.

[
{"id": <id1>, "certificate_hash": <certificate1_hash>, "timestamp": <timestamp1>},
{"id": <id2>, "certificate_hash": <certificate2_hash>, "timestamp": <timestamp2>}
]

DELETE:

Query supported. An empty query deletes all revoked certificates and returns nil on success.

Authentication

A device can authenticate (i.e., receive a token) using mTLS by sending an HTTP POST request to port 444 of the relevant URL.

The following curl can be used as an example:

curl -X POST "https://yourURL.com:444/api/v/4/devices/mtls/auth" -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"system_key": "yourSystemKey", "name": "yourDeviceName"}' --cert "path/to/yourDeviceCert.pem" --key "path/to/yourDeviceKey.pem"

The returned response will contain a device token.

Similarly, this Python code can be used as an example:

import requests

url = "https://yourURL.com:444/api/v/4/devices/mtls/auth"
headers = {"Content-Type": "application/json", "Accept": "application/json"}
data = '{"system_key": "yourSystemkey", "name": "yourDeviceName"}'
resp = requests.post(url, headers=headers, data=data, verify=True, cert=("path/to/yourDeviceCert.pem", "path/to/yourDeviceKey.pem"))

deviceToken = str(resp["deviceToken"])

ALPN (Application Layer Protocol Negotiation)

ClearBlade supports mTLS authentication for devices connecting via MQTT using ALPN on port 444. The ALPN protocol name is clearblade_mqtt_mtls. Device Just-in-Time (JIT) provisioning is also supported. A Root CA certificate must be added via the mTLS admin endpoints before connecting devices via mTLS.

To connect to MQTT using mTLS, the device needs to set the following in the MQTT Connect packet:

  1. The Username field must be a stringified JSON object with the device name set, amongst other column values, if required for JIT provisioning. For example: '{"name": "myDevice"}'

  2. The Password field must contain the system key.

Here’s a Python example using the Paho MQTT client:

from __future__ import print_function
import sys
import ssl
import time
import datetime
import logging, traceback
import paho.mqtt.client as mqtt
IoT_protocol_name = "clearblade_mqtt_mtls"
cb_iot_endpoint = "<CLEARBLADE_URL>" # For example test.clearblade.com
cert = "<DEVICE_CERTIFICATE_FILE>"
private = "<DEVICE_PRIVATE_KEY_FILE>"
username = '{"name": "device-1"}'
password = "<SYSTEM_KEY>"
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler(sys.stdout)
log_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(log_format)
logger.addHandler(handler)
def ssl_alpn():
    try:
        #debug print opnessl version
        logger.info("open ssl version:{}".format(ssl.OPENSSL_VERSION))
        ssl_context = ssl.create_default_context()
        ssl_context.set_alpn_protocols([IoT_protocol_name])
        ssl_context.load_cert_chain(certfile=cert, keyfile=private)
        return  ssl_context
    except Exception as e:
        print("exception ssl_alpn()")
        raise e
if __name__ == '__main__':
    topic = "test/date"
    try:
        mqttc = mqtt.Client(client_id="<CLIENT_ID>")
        ssl_context= ssl_alpn()
        mqttc.tls_set_context(context=ssl_context)
        mqttc.username_pw_set(username=username, password=password)
        logger.info("start connect")
        mqttc.connect(cb_iot_endpoint, port=444)
        logger.info("connect success")
        mqttc.loop_start()
        while True:
            now = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
            logger.info("try to publish:{}".format(now))
            mqttc.publish(topic, now)
            time.sleep(1)
    except Exception as e:
        logger.error("exception main()")
        logger.error("e obj:{}".format(vars(e)))
        logger.error("message:{}".format(e.message))
        traceback.print_exc(file=sys.stdout)