← projects
Thistle Technologies · production

Certificate-Based Auth for MQTT

PKI-issued device identity for secure IoT communication

PKIX.509mTLSMQTTRoot + Subordinate CAs
// 01 — problem

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.

// 02 — approach
  • 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.
// 03 — result

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.

// 04 — key decisions
Why split /enroll and /identity

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.

Why generate certificates on demand

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.

Why mTLS over username/password on MQTT

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.

// 05 — further reading