This is a development version of the documentation. Content may change without notice.
Voke Documentation
PLC / Devices

Auth methods

Three MQTT listeners, same topic tree, three auth models. Choose one per deployment.

Voke's Mosquitto broker exposes three separate listeners on different ports — one per auth model. All three sit on the same topic namespace (cpi/{plantId}/…) and all three enforce TLS at the transport layer. Pick the one that fits your security posture and PLC capabilities.


Decision table

ListenerPort (prod / dev)Auth mechanismTLSBest for
mTLS8886 / 8883X.509 client certificateMutual (client + server)Production — strongest identity, offline/headless PLCs, long-lived identities
JWT8887 / 8884RS256-signed JWT as MQTT passwordServer onlyManaged devices with rotating credentials issued dynamically
PASSWORD8885 / 8885Short username + bcrypt-hashed passwordServer onlyLocal dev, CI smoke tests, PLCs without crypto support

The PASSWORD port is identical in production and local dev (8885). mTLS and JWT ports differ: 8886/8887 in production, 8883/8884 locally.


Security trade-offs

mTLS

  • Highest assurance. The device's private key never leaves the device; the broker rejects any connection whose cert was not signed by Voke's root CA.
  • Revocation is CRL-based (ca.crl mounted into the broker). Re-running init-ca.sh invalidates all existing device certificates at once; generate-device-cert.sh issues replacements per plant.
  • Ops overhead. Cert issuance is a one-time setup per plant; rotation (every 2 years by default) requires running the issuance script and pushing the new files to the device.
  • ACL. The broker sets use_identity_as_username true, so Mosquitto derives the MQTT username from the cert's CN field. The ACL file maps each CN to exactly its own plant topics via pattern rules.

JWT

  • Flexible credential lifetime. Tokens are short-lived (default 1 hour, max 24 hours). Re-issue without touching the device's long-term identity: you only swap a signed blob.
  • Key format is critical. The wiomoc/mosquitto-jwt-auth v0.4.0 plugin requires the RSA public key in PKCS#1 DER format. SPKI DER fails with InvalidSignature. See the JWT onboarding page for the conversion command.
  • ARM64 limitation. The plugin is amd64-only. The broker entrypoint removes the JWT listener on Apple Silicon; use PASSWORD or mTLS for local dev on M-series Macs.
  • Claims. The sub claim must equal the plant UUID (PLANT_ID). exp is validated; plugin_opt_jwt_validate_sub_match_username true means the MQTT username field must also equal the sub value.

PASSWORD

  • Simplest PLC code. Credentials are provisioned via POST /api/v1/plants/{plantId}/provision (or the admin SPA Security tab) and written into the Mosquitto password file by MqttPasswordService. The username format is plc-<first 8 hex chars of plantId>.
  • Rotation calls the same provisioning endpoint again; MqttPasswordService atomically replaces the entry and sends SIGHUP to Mosquitto.
  • Not for high-assurance production. Passwords are long-lived until explicitly rotated. Use mTLS or JWT if you need short-lived credentials or a cryptographic identity guarantee.

What all three listeners share

  • TLS transport. Every listener (including PASSWORD) uses a server TLS certificate issued by the Voke PKI. PLCs must trust the Voke CA root (ca.crt) or the system trust store if the broker cert is signed by a public CA.
  • Same topic tree. cpi/{plantId}/telemetry, cpi/{plantId}/command, cpi/{plantId}/ack, cpi/{plantId}/status, cpi/{plantId}/alarm, cpi/{plantId}/info. No listener has a different topic prefix.
  • HMAC message signing. Telemetry and command-ack envelopes carry an HMAC-SHA256 signature computed from the plant's HMAC secret (provisioned alongside MQTT credentials). All three auth methods use the same signing contract. See HMAC signing for the canonical algorithm.
  • Per-plant ACL. No plant can publish to another plant's topics regardless of auth method. mTLS and JWT use pattern ACLs (pattern write cpi/%u/telemetry etc.); PASSWORD uses per-plant explicit entries written by MqttPasswordService.

Choosing for your deployment

ScenarioRecommended listener
Production plant on a cellular modem (no internet key rotation)mTLS
Production plant managed by a fleet service that issues tokensJWT
Staging / integration environmentJWT or PASSWORD
Local developer laptopPASSWORD (or mTLS if certs are already set up)
Apple Silicon local devPASSWORD (JWT listener is disabled on ARM64)
CI / automated smoke testsPASSWORD

Next steps

On this page