You Want Electronic Components for your project. 

For more information, contact us at: 

Implement Authentication and Access Control for IoT Systems



Encryption protects data in transit. Authentication ensures only legitimate devices and users can connect. Access control ensures that once connected, each entity can only perform authorised actions. Together, these three layers form a complete security posture for any IoT deployment.

KEY
Authentication answers ‘WHO are you?’  •  Access control answers ‘WHAT are you allowed to do?’  •  Encryption answers ‘Can anyone else READ what you’re doing?’ All three are required for a properly secured IoT system. Missing any one leaves a significant attack surface.

1. Username and Password Authentication

Mosquitto — Username/Password Authentication Setup
# Create password file with device credentials
sudo mosquitto_passwd -c /etc/mosquitto/passwd esp32-sensor-01

# Add more devices without overwriting the file:
sudo mosquitto_passwd -b /etc/mosquitto/passwd esp32-sensor-02 pass2
sudo mosquitto_passwd -b /etc/mosquitto/passwd dashboard-user dashpass

# Configure Mosquitto: /etc/mosquitto/conf.d/auth.conf
allow_anonymous false
password_file   /etc/mosquitto/passwd

sudo systemctl restart mosquitto

C/C++ — ESP32 MQTT with Username/Password
// Connect with unique per-device credentials
if (mqtt.connect("esp32-sensor-01",
                 "esp32-sensor-01",     // Username
                 "my_secure_pass_123")) {  // Password
  Serial.println("Authenticated connection successful.");
} else {
  Serial.print("Auth failed: "); Serial.println(mqtt.state());
  // rc=-4 = Connection refused, not authorised
}

// Best practice: load from NVS (not hardcoded):
// String user = prefs.getString("mqtt_user", "");
// String pass = prefs.getString("mqtt_pass", "");
// mqtt.connect(clientId, user.c_str(), pass.c_str());

2. Token-Based Authentication

Token type Description and IoT use
ThingsBoard access token Each device has a unique 20-character token. Token = MQTT username. Rotatable from ThingsBoard UI without reflashing if stored in NVS.
HTTP API key Unique write/read keys per channel. Passed as header or query parameter. Provides channel-level access control.
JWT (JSON Web Token) Short-lived tokens issued after login. Used for ThingsBoard REST API. Contains identity claims and expires after configurable time.
Token security rules (1) Unique token per device. (2) Store in NVS, never in source code. (3) Rotate every 90 days for production. (4) Revoke compromised tokens immediately from cloud console.

3. Mutual TLS (mTLS) — Certificate-Based Device Identity

In standard TLS, only the server presents a certificate. In Mutual TLS (mTLS), BOTH sides present certificates. The broker verifies that the connecting device holds a valid, known certificate. This is the strongest device authentication method and is used by AWS IoT Core, Azure IoT Hub, and Google Cloud IoT by default.

Mosquitto — Require Client Certificates (mTLS)
# Add to /etc/mosquitto/conf.d/tls.conf:
require_certificate      true   # Force all clients to present a certificate
use_identity_as_username true   # Use certificate CN as MQTT username

# Generate per-device certificate (repeat for each device):
openssl genrsa -out device01.key 2048
openssl req -new -key device01.key -out device01.csr \
  -subj "/CN=esp32-device-01/O=NEDU/C=RW"
openssl x509 -req -days 3650 -in device01.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial -out device01.crt

# Each ESP32 device needs three files embedded in firmware:
# ca.crt (verify broker) + device01.crt + device01.key

C/C++ — ESP32 Mutual TLS with Client Certificate
#include <WiFiClientSecure.h>

// Embed all three certificates as string literals in firmware
const char* CLIENT_CERT = "-----BEGIN CERTIFICATE-----\n"
                          "... device01.crt content ...\n"
                          "-----END CERTIFICATE-----\n";

const char* CLIENT_KEY  = "-----BEGIN RSA PRIVATE KEY-----\n"
                          "... device01.key content ...\n"
                          "-----END RSA PRIVATE KEY-----\n";

const char* CA_CERT     = "-----BEGIN CERTIFICATE-----\n"
                          "... ca.crt content ...\n"
                          "-----END CERTIFICATE-----\n";

WiFiClientSecure tlsClient;

void setup() {
  tlsClient.setCACert(CA_CERT);         // Verify broker identity
  tlsClient.setCertificate(CLIENT_CERT); // Present device identity
  tlsClient.setPrivateKey(CLIENT_KEY);  // Sign with device private key

  PubSubClient mqtt(tlsClient);
  mqtt.setServer(BROKER_HOST, 8883);
  // No username/password needed — certificate IS the authentication
  if (mqtt.connect("esp32-device-01")) {
    Serial.println("mTLS authenticated!");
  }
}

KEY
mTLS is the gold standard for production IoT authentication. Each device has a unique X.509 certificate signed by a CA you control. Compromising one device certificate does not compromise any other device. Used by AWS IoT Core, Azure IoT Hub by default.

MQTT Access Control Lists (ACLs)

Authentication determines who can connect. ACLs determine what topics each connected client can publish to and subscribe from. Without ACLs, an authenticated sensor could subscribe to another device’s command topics and inject malicious commands.

Mosquitto ACL Configuration — Topic-Level Permissions
# /etc/mosquitto/acl
# Sensor 01: publish only to its own data topic, receive only its own commands
user esp32-sensor-01
topic write sensors/kigali/sensor01/#
topic read  devices/sensor01/cmd/#

user esp32-sensor-02
topic write sensors/kigali/sensor02/#
topic read  devices/sensor02/cmd/#

# Dashboard: read-only access to all sensor data
user dashboard-user
topic read sensors/#
topic read devices/#

# Admin: full access
user iot-admin
topic readwrite #

# Reference ACL file in /etc/mosquitto/conf.d/auth.conf:
# acl_file /etc/mosquitto/acl

KEY
ACLs enforce the principle of least privilege: each entity can only perform the minimum actions required for its function. A sensor should NEVER be able to subscribe to command topics for other devices, publish to admin topics, or read other sensors’ data streams.

ThingsBoard Role-Based Access Control (RBAC)

Role Permissions IoT example
Tenant Admin Full access to all devices, dashboards, and settings within their tenant. Can create users, devices, and rules. IT manager / system owner
Customer Access limited to specific devices and dashboards assigned to their account. Hospital department head sees only ward devices
Customer User Read-only or limited write access within a customer account. Cannot manage devices. Nurse views patient room dashboard only
Public Dashboard Share a dashboard publicly (no login required). Read-only, filtered to specific devices. Public air quality display in government office
Device Profile Defines what operations a device token can perform: publish telemetry, receive RPC, update attributes. Restricts sensor from accessing other tenant data

Device Provisioning at Scale

For deployments with many devices, manually creating credentials for each device is impractical. ThingsBoard device provisioning allows a shared key to be used once per device to obtain a unique credential:

ThingsBoard — Zero-Touch Device Provisioning on First Boot
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Preferences.h>

const char* PROV_HOST  = "https://thingsboard.cloud/api/v1/provision";
const char* PROV_KEY   = "shared_provisioning_key_embedded_in_all_devices";
const char* PROV_SECR  = "provisioning_secret";

String provisionDevice() {
  HTTPClient http;
  http.begin(PROV_HOST);
  http.addHeader("Content-Type", "application/json");

  StaticJsonDocument<256> req;
  req["deviceName"]              = "ESP32-" + String((uint32_t)ESP.getEfuseMac(), HEX);
  req["provisionDeviceKey"]      = PROV_KEY;
  req["provisionDeviceSecret"]   = PROV_SECR;
  char body[256]; serializeJson(req, body);

  int code = http.POST(body);
  if (code == 200) {
    StaticJsonDocument<128> doc;
    deserializeJson(doc, http.getString());
    return doc["credentialsValue"].as<String>();
  }
  return "";
}

void setup() {
  Preferences prefs;
  prefs.begin("creds", false);
  String token = prefs.getString("tb_token", "");

  if (token.length() == 0) {
    token = provisionDevice();   // First boot: get unique token
    prefs.putString("tb_token", token);
  }
  // Use token for subsequent MQTT connections...
}

12-Point Security Hardening Checklist

Before deploying any IoT device to a production environment, verify all items on this checklist:

☐
All MQTT connections use TLS on port 8883. No plain port 1883 in production.
☐
All HTTP requests use HTTPS (port 443). No plain HTTP in production firmware.
☐
Every device has a unique credential (token, username/password, or certificate). No shared credentials.
☐
Credentials are stored in ESP32 NVS, not hardcoded in source code.
☐
Source code repository has no credentials or API keys committed (use .gitignore and enable secret scanning).
☐
MQTT broker requires authentication (allow_anonymous false). ACLs restrict each client to minimum required topics.
☐
OTA firmware updates are signed and verified before installation.
☐
Debug UART/JTAG serial interface is disabled in production firmware.
☐
Data at rest on broker or cloud is encrypted (server-side encryption enabled).
☐
A data retention policy is defined: old telemetry is deleted after the defined period.
☐
Anomaly detection alarms are configured to detect impossible sensor values (potential injection attacks).
☐
An incident response plan exists: how to revoke credentials, patch compromised devices, and notify stakeholders.

Check Your Understanding — Lesson 8.3

?
1. Explain the difference between authentication and access control. A student configures MQTT username/password authentication but no ACL. What can an authenticated sensor do that it should NOT be able to do?
?
2. Describe the THREE artefacts an ESP32 device needs to establish a mutual TLS connection with a Mosquitto broker, and explain what each one is used for during the connection.
?
3. A company deploys 200 IoT sensors. Using the shared provisioning key pattern, explain how each sensor can obtain its own unique credential on first boot without the firmware containing a unique secret per device.

I'm an Embedded & AIoT Systems Engineer and the Founder & CEO of Nyereka Tech, a Rwanda-based startup enabling access to STEM tools, training, and innovation. I'm passionate about empowering young innovators through practical technology education and local manufacturing solutions.