Certificate-Based Auth for MQTT
PKI-issued device identity for secure IoT communication
IoT devices typically talk to backend services over MQTT — lightweight, great for constrained environments, but on its own it has no way to prove who's on either end of the wire. Username/password auth is impractical for non-interactive fleets and rotating shared credentials at scale is a losing game. The platform needs to guarantee that only authorized devices can connect, that traffic is encrypted, and that no message can be tampered with in flight.
- 01Hierarchical PKI: an offline Root CA anchors trust and issues to Subordinate CAs that sign device and server certificates — compartmentalization, separate sub-CAs per purpose, and revocation that doesn't take down the whole system.
- 02Two-step device provisioning. Step 1 — POST /enroll with a Thistle-Device-Enrollment-Token header returns a per-device device_token (and device_id, project_id). The enrollment token can be regenerated at any time, immediately invalidating prior tokens.
- 03Step 2 — GET /identity with Authorization: Bearer <device_token> returns the device's X.509 certificate (signed by the Subordinate CA), its private key, and device_id. Certificates are generated on demand — the server never stores them, minimizing exposure of private keys.
- 04The device uses that cert + key to connect to the MQTT broker over mTLS. The broker validates the signature against the Subordinate CA, the validity period, and CRL/deny-list status before any topic is published or subscribed.
- 05The certificate's Common Name carries the device_id, binding the cryptographic identity to a specific device — every downstream service can authorize off the cert chain.
Devices boot with no shared secrets. Each one has its own cryptographic identity, so compromise of one device cannot impersonate another and lateral movement is blocked. Enrollment is rate-limited and auditable independently of the steady-state path. Long-lived device certificates keep operations simple, while server-side CRL + device_id deny-listing keep revocation a control-plane action — not a firmware ship.
Bootstrap (proving you're allowed to join) and steady-state (proving who you are) have different threat models. Separate endpoints let us use different auth mechanisms — enrollment-token header vs. Bearer device_token — and rate-limit / audit enrollment without touching the hot path.
Pre-generating and storing per-device certs would mean holding a pile of private keys server-side. On-demand generation means the private key is transmitted exactly once, over HTTPS, and never sits at rest in our infrastructure.
Credentials in a non-interactive fleet are a rotation nightmare and offer no message-level guarantees. mTLS gives mutual authentication, encryption, and integrity in one handshake — and the same certificate becomes the authorization principal for broker topic policy.
