Compare access control models (MAC, DAC, RBAC, ABAC)
Implement OAuth 2.0 for IoT applications
Design identity management for device fleets
Choose appropriate authentication mechanisms for IoT constraints
For Beginners: Access Control for IoT
Access control determines what each user or device is allowed to do in an IoT system. Think of a hospital where doctors, nurses, and visitors each have different access levels – doctors can prescribe medication, nurses can administer it, and visitors can only visit patients. Similarly, IoT access control ensures each device and user can only perform actions appropriate to their role.
Sensor Squad: Choosing the Right Lock System!
“There are five different ways to control who can do what in an IoT system!” Max the Microcontroller announced, laying out the options. “Picking the right one depends on how complex your system is and how many devices you manage.”
Sammy the Sensor started with the basics. “MAC – Mandatory Access Control – is like a military base where the SYSTEM decides who gets access, not the users. Very secure but very rigid. DAC – Discretionary Access Control – is the opposite: the OWNER decides, like how you control who sees your social media posts. Simple but not great for big organizations.”
“RBAC is the sweet spot for most IoT platforms,” Lila the LED said. “You create roles like Admin, Operator, and Viewer, and assign permissions to each role. Then you just assign users to roles. Managing 1,000 users with 5 roles is way easier than managing 1,000 individual permission sets!”
“OAuth 2.0 is how modern cloud IoT platforms handle all of this,” Bella the Battery explained. “Your smart home app uses OAuth to get an access token from the cloud. The token says ‘this user can control lights and read temperature but cannot change the security system.’ The beauty is that the device never sees your actual password – only the limited-access token. Even if someone intercepts the token, they can only do what the token allows, and it expires after a short time!”
How It Works: ABAC Policy Evaluation Engine
Attribute-Based Access Control evaluates access requests using a multi-step decision process:
Step 1: Collect Attributes
Subject attributes: User ID, role, department, clearance_level, MFA_verified
Environment attributes: Current time, day_of_week, network_zone, threat_level
Step 2: Match Policies For each policy in the system, check if the action matches:
Policy: "operator-control-actuators"
IF action == "actuator:control" → Continue to conditions
IF action != "actuator:control" → Skip this policy
Step 3: Evaluate Conditions All conditions in the policy must be TRUE:
subject.role IN ["operator", "admin"]
resource.type == "actuator"
environment.hour >= 6 AND environment.hour <= 22
→ Policy matches, effect = ALLOW
Step 4: Apply Precedence Rules
Deny policies override allow policies: If ANY policy says DENY, access denied
Default deny: If NO policy matches, access denied
Audit all decisions: Log which policy determined the outcome
Real-World Example: Smart factory actuator control - Operator Bob requests “control actuator valve-42” at 14:00 - Subject: {role: “operator”, department: “production”} - Resource: {type: “actuator”, owner_dept: “production”, criticality: “medium”} - Environment: {hour: 14, day: “weekday”, threat_level: “normal”} - Policy “operator-control” matches: role=operator, time=work_hours, same_department - Result: ALLOW (but if time=03:00, DENY due to time restriction)
Key Insight: ABAC scales better than RBAC because adding a new attribute (e.g., “device_health_status”) does not require creating new roles. Policies automatically adapt to new context.
10.2 Access Control Models
10.2.1 Comparison of Access Control Models
Model
Description
IoT Use Case
Complexity
MAC (Mandatory)
System enforces policies
Military, classified
High
DAC (Discretionary)
Owner controls access
Personal devices
Low
RBAC (Role-Based)
Permissions by role
Enterprise IoT
Medium
ABAC (Attribute-Based)
Policy-based on attributes
Multi-tenant, dynamic
High
The principle of least privilege applies across all models: every user and device should receive only the minimum permissions needed for their function, regardless of which access control model is used.
Role-Based Access Control architecture showing users assigned to roles with associated permissions
Tradeoff: RBAC vs ABAC
Factor
RBAC
ABAC
Setup Complexity
Low (define 5-10 roles)
High (policy engine + attributes)
Ongoing Maintenance
Medium (add roles as needs grow)
Low (policies adapt automatically)
Scalability
Poor (role explosion >100 user types)
Excellent (attributes scale)
Context Awareness
Limited (role only)
Full (time, location, device state)
Audit Trail
Simple (“Admin accessed X”)
Detailed (“User accessed X via policy P1 at time T in zone Z”)
Performance
Excellent (<1ms lookup)
Good (policy evaluation ~5-10ms)
Best For
Small-medium deployments (<1,000 devices)
Large multi-tenant platforms (>10,000 devices)
Choose RBAC when: You have well-defined user categories with stable permissions and fewer than ~100 distinct role combinations. Choose ABAC when: You need dynamic, context-aware access decisions or have multi-tenant deployments where role explosion becomes unmanageable.
10.2.3 Attribute-Based Access Control (ABAC) Example
This policy allows operators to control actuators only if: - Operator’s department matches device owner - Device is not high-criticality - Time is during working hours - Operator is in authorized location
OAuth 2.0 enables secure third-party access without sharing credentials:
OAuth 2.0 authorization flow for IoT showing token exchange between device, authorization server, and resource server
10.3.1 OAuth 2.0 Grant Types for IoT
Grant Type
Use Case
Security Level
Device Code
Devices without browser
High
Client Credentials
Server-to-server, device identity
High
Authorization Code + PKCE
Mobile companion apps
High
Refresh Token
Long-lived device sessions
Medium
Never use Implicit Grant or Resource Owner Password Grant for IoT – these are deprecated in the OAuth 2.1 specification and are insecure because they expose tokens in browser history or transmit passwords directly.
Try It: OAuth 2.0 Grant Type Advisor for IoT
Show code
viewof oauth_deviceType = Inputs.select( ["Constrained sensor (no display)","Gateway with display","Mobile companion app","Server/backend service","Smart speaker/TV","Industrial PLC"], {label:"Device Type",value:"Constrained sensor (no display)"})viewof oauth_hasBrowser = Inputs.toggle({label:"Device has browser capability?",value:false})viewof oauth_hasUserInteraction = Inputs.toggle({label:"User present during auth?",value:false})viewof oauth_tokenLifetime = Inputs.select( ["Short (minutes)","Medium (hours)","Long (days/weeks)","Persistent (months)"], {label:"Desired Token Lifetime",value:"Medium (hours)"})viewof oauth_m2mOnly = Inputs.toggle({label:"Machine-to-machine only (no human user)?",value:true})
Show code
oauth_result = {const device = oauth_deviceType;const browser = oauth_hasBrowser;const userPresent = oauth_hasUserInteraction;const lifetime = oauth_tokenLifetime;const m2m = oauth_m2mOnly;let recommended ="";let explanation ="";let securityLevel ="";let secColor ="";let flow = [];let warnings = [];if (m2m &&!userPresent) { recommended ="Client Credentials"; explanation ="Best for machine-to-machine communication where no human user is involved. The device authenticates using its own credentials (client ID + secret or certificate)."; securityLevel ="High"; secColor ="#16A085"; flow = ["Device sends client_id + client_secret to auth server","Auth server validates credentials","Auth server returns access_token","Device uses token to access resources"]; } elseif (!browser && userPresent) { recommended ="Device Code"; explanation ="Ideal for devices without a browser. The device displays a code that the user enters on a separate device (phone/computer) to authorize access."; securityLevel ="High"; secColor ="#16A085"; flow = ["Device requests device_code + user_code from auth server","Device displays user_code (or URL) to user","User enters code on phone/computer browser","Device polls auth server until user authorizes","Auth server returns access_token"]; } elseif (browser && userPresent) { recommended ="Authorization Code + PKCE"; explanation ="Best for devices with browser capability where a user is present. PKCE (Proof Key for Code Exchange) prevents authorization code interception attacks."; securityLevel ="High"; secColor ="#16A085"; flow = ["Device generates code_verifier + code_challenge","Redirects user to auth server with code_challenge","User authenticates and grants consent","Auth server redirects back with authorization_code","Device exchanges code + code_verifier for access_token"]; } else { recommended ="Client Credentials"; explanation ="Default for autonomous devices. Consider adding device attestation for higher security."; securityLevel ="High"; secColor ="#16A085"; flow = ["Device sends client_id + client_secret to auth server","Auth server validates credentials","Auth server returns access_token","Device uses token to access resources"]; }const needsRefresh = lifetime ==="Long (days/weeks)"|| lifetime ==="Persistent (months)";if (needsRefresh) { warnings.push("Use Refresh Tokens to maintain long-lived sessions without storing long-lived access tokens."); }if (device ==="Constrained sensor (no display)"&& userPresent) { warnings.push("Constrained sensors typically cannot display codes -- consider a companion app to handle user interaction."); }if (!m2m &&!userPresent) { warnings.push("If no user is present and it is not pure M2M, consider pre-provisioned device certificates instead of OAuth."); }return {recommended, explanation, securityLevel, secColor, flow, warnings, needsRefresh};}
10.4 Device Provisioning and Certificate Lifecycle
The following interactive tools demonstrate the complete lifecycle of device provisioning – from certificate issuance through credential management and security best practices.
Interactive: Certificate Lifecycle Management
Interactive: Device Provisioning Flow Visualizer
Interactive: Provisioning Method Comparison
Interactive: Device Credentials Management
Interactive: Provisioning Security Best Practices
Interactive: Device Provisioning Visualizer
10.5 Identity Management for Device Fleets
10.5.1 IAM vs IRM
Aspect
IAM (Identity Access Management)
IRM (Identity Resource Management)
Focus
Human users
Machine identities (devices, services)
Scale
Thousands of users
Millions of devices
Lifecycle
Onboarding → Offboarding
Provisioning → Decommissioning
Authentication
Passwords, MFA
Certificates, keys
Credential Rotation
User-initiated
Automated
10.5.2 Certificate-Based Device Identity
Certificate-based device identity provisioning during manufacturing
10.6 Real-World Access Control Implementations
10.6.1 AWS IoT Core Policy System
AWS IoT uses ABAC-style policies for device permissions. Here is a real policy limiting a temperature sensor to publish only to its own topic:
Per-device topic isolation: ${iot:Connection.Thing.ThingName} is replaced at runtime with the authenticated device name, preventing device A from publishing as device B
Explicit deny for commands: Even if a broader policy grants access, the explicit deny prevents devices from issuing commands to other devices
Principle of least privilege: Sensors can publish telemetry and receive commands, but cannot publish commands or subscribe to other devices’ data
Best Practice: Assign the narrowest role needed. A monitoring dashboard should use Data Reader, not Data Contributor, even if the broader role “works.”
150,000 cameras accessed, including hospitals and prisons
Wyze camera data leak (2022)
Overly permissive web API, no per-device auth
13,000 users saw other users’ camera feeds
MOVEit Transfer (2023)
SQL injection bypassing auth
2,700+ organizations, 95M+ records
Common Pattern: Every major IoT breach involved either missing authentication, overly broad permissions, or hard-coded credentials. Proper access control would have prevented or limited all four incidents.
10.7 Worked Example: Certificate Management for IoT Fleet
Scenario: A utility company manages 50,000 smart meters. Each meter needs a unique X.509 certificate for mTLS authentication to the backend. Certificates expire after 2 years and must be renewed automatically without service disruption.
Solution Architecture:
Manufacturing: Each meter generates key pair in secure element, CSR submitted to enrollment server
Enrollment: EST (RFC 7030) protocol issues certificate from organizational CA
Operation: Meters authenticate with mTLS to data collection servers
Renewal: Automated re-enrollment 30 days before expiry using existing certificate
Revocation: Compromised meters added to CRL, OCSP updated in real-time
Key Design Decisions:
Private keys never leave device: Generated in secure element, CSR signed on-device
Short-lived bootstrap credentials: Initial enrollment uses one-time token that expires
ECDSA P-256 over RSA: Smaller certificates (64-byte signatures vs. 256 bytes for RSA-2048), faster verification for constrained devices
30-day renewal window: Allows time for retry on network failures
EST over SCEP: Modern protocol (RFC 7030) with TLS-based transport and better security properties than the legacy SCEP protocol
Metrics After 12 Months:
Metric
Before
After
Improvement
Expired cert incidents
47/year
3/year
94% reduction
Manual cert operations
200/month
12/month
94% reduction
Average renewal time
45 minutes
3 seconds
99.9% faster
Security audit findings
8 critical
0 critical
100% remediation
Try It: ABAC Policy Engine for IoT
Run this Python code to implement an Attribute-Based Access Control policy engine. Test it with various IoT scenarios – device control, data access, and firmware updates – to see how attributes determine access decisions.
from datetime import datetimeclass ABACPolicyEngine:"""Attribute-Based Access Control engine for IoT systems."""def__init__(self):self.policies = []self.audit_log = []def add_policy(self, name, effect, action, conditions):self.policies.append({"name": name, "effect": effect,"action": action, "conditions": conditions })def evaluate(self, subject, action, resource, environment):"""Evaluate access request against all policies.""" request = {"subject": subject, "action": action,"resource": resource, "environment": environment } matching_policies = []for policy inself.policies:if policy["action"] != action and policy["action"] !="*":continueifself._check_conditions(policy["conditions"], request): matching_policies.append(policy)# Deny takes precedence over allowfor p in matching_policies:if p["effect"] =="deny":self._log(request, "DENY", p["name"])returnFalse, p["name"]for p in matching_policies:if p["effect"] =="allow":self._log(request, "ALLOW", p["name"])returnTrue, p["name"]# Default denyself._log(request, "DENY", "default-deny")returnFalse, "default-deny"def _check_conditions(self, conditions, request):for key, expected in conditions.items(): parts = key.split(".") value = requestfor p in parts: value = value.get(p, None)if value isNone:returnFalseifcallable(expected):ifnot expected(value):returnFalseelifisinstance(expected, list):if value notin expected:returnFalseelif value != expected:returnFalsereturnTruedef _log(self, request, decision, policy):self.audit_log.append({"subject": request["subject"].get("id"),"action": request["action"],"resource": request["resource"].get("id"),"decision": decision,"policy": policy, })# === Set up IoT access control policies ===engine = ABACPolicyEngine()# Policy 1: Operators can control actuators during work hoursengine.add_policy( name="operator-control", effect="allow", action="actuator:control", conditions={"subject.role": ["operator", "admin"],"resource.type": "actuator","environment.hour": lambda h: 6<= h <=22, })# Policy 2: Sensors can only publish to their own topicengine.add_policy( name="sensor-publish", effect="allow", action="mqtt:publish", conditions={"subject.type": "sensor","resource.topic_owner": lambda owner: True, # checked below })# Policy 3: Admin can update firmware anytimeengine.add_policy( name="admin-firmware", effect="allow", action="firmware:update", conditions={"subject.role": "admin","subject.mfa_verified": True, })# Policy 4: Block all access from quarantined devicesengine.add_policy( name="quarantine-block", effect="deny", action="*", conditions={"subject.quarantined": True, })# === Test scenarios ===print("=== IoT ABAC Policy Engine ===\n")scenarios = [ {"name": "Operator controls valve during work hours","subject": {"id": "user-42", "role": "operator", "type": "human","quarantined": False, "mfa_verified": False},"action": "actuator:control","resource": {"id": "valve-001", "type": "actuator"},"environment": {"hour": 14}, }, {"name": "Operator controls valve at 3 AM","subject": {"id": "user-42", "role": "operator", "type": "human","quarantined": False, "mfa_verified": False},"action": "actuator:control","resource": {"id": "valve-001", "type": "actuator"},"environment": {"hour": 3}, }, {"name": "Admin updates firmware with MFA","subject": {"id": "admin-01", "role": "admin", "type": "human","quarantined": False, "mfa_verified": True},"action": "firmware:update","resource": {"id": "gateway-05", "type": "gateway"},"environment": {"hour": 10}, }, {"name": "Admin updates firmware WITHOUT MFA","subject": {"id": "admin-01", "role": "admin", "type": "human","quarantined": False, "mfa_verified": False},"action": "firmware:update","resource": {"id": "gateway-05", "type": "gateway"},"environment": {"hour": 10}, }, {"name": "Quarantined device tries to control actuator","subject": {"id": "sensor-99", "role": "operator", "type": "sensor","quarantined": True, "mfa_verified": False},"action": "actuator:control","resource": {"id": "valve-001", "type": "actuator"},"environment": {"hour": 14}, }, {"name": "Viewer tries to control actuator (no permission)","subject": {"id": "user-99", "role": "viewer", "type": "human","quarantined": False, "mfa_verified": False},"action": "actuator:control","resource": {"id": "valve-001", "type": "actuator"},"environment": {"hour": 14}, },]for s in scenarios: allowed, policy = engine.evaluate( s["subject"], s["action"], s["resource"], s["environment"] ) status ="ALLOW"if allowed else"DENY "print(f" [{status}] {s['name']}")print(f" Policy: {policy}")# Print audit logprint(f"\n--- Audit Log ({len(engine.audit_log)} entries) ---")for entry in engine.audit_log:print(f" {entry['subject']:>12} | {entry['action']:<20} | "f"{entry['resource']:<12} | {entry['decision']:<5} | {entry['policy']}")
What to Observe:
The operator is allowed during work hours (6-22) but denied at 3 AM – time-based context matters
Admin firmware updates require MFA verification – even admins need additional proof
Quarantined devices are denied everything (deny policy overrides allow policies)
Viewers have no matching allow policy, so default-deny kicks in
The audit log captures every access decision for compliance (HIPAA, GDPR)
ABAC provides fine-grained control that RBAC alone cannot achieve (time, location, device state)
Worked Example: AWS IoT Policy Design for Multi-Tenant Fleet
Scenario: A logistics company operates 10,000 delivery vehicles across 50 customers. Each vehicle has GPS, temperature sensors, and door-open sensors. Design IAM policies ensuring customers can ONLY access their own vehicles.
Test 1: vehicle-acme-001 publishes to devices/vehicle-acme-001/telemetry
Result: ALLOWED (matches ${iot:Connection.Thing.ThingName})
Test 2: vehicle-acme-001 publishes to devices/vehicle-zeta-157/telemetry
Result: DENIED (Deny rule blocks cross-customer access)
Test 3: vehicle-acme-001 subscribes to devices/vehicle-acme-*/commands
Result: DENIED (wildcard subscription not allowed, must use exact Thing name)
Test 4: Attacker creates Thing named "vehicle-acme-001-hacked"
Result: Device can publish, but customers query by ThingName prefix
Customer "acme" only sees Things matching "vehicle-acme-[0-9]{3}"
Attacker Thing is invisible to legitimate customer queries
Key Design Decisions:
Thing name as authorization token: ${iot:Connection.Thing.ThingName} ensures devices can ONLY access their own topics
Explicit deny for wildcards: Prevents vehicle-acme-* subscriptions that could leak other vehicles’ data
Customer ID in Thing name: Enables per-customer query isolation in backend
No cross-vehicle commands: Even within same customer, vehicles cannot command each other
Cost Impact:
10,000 vehicles x 100 messages/day x 30 days = 30 million messages/month
At $0.08 per million messages: 30 x $0.08 = $2.40/month for messaging
Policy evaluation overhead: <1ms per message (negligible)
Impact: Any compromised device can: - Publish to ALL topics (impersonate other devices) - Subscribe to ALL topics (eavesdrop on entire fleet) - Update device shadows globally (manipulate all devices) - Create/delete Things (denial of service)
Real incident (2021): IoT startup gave all devices wildcard permissions. One compromised sensor published fake temperature data to 5,000 other devices’ topics, triggering emergency shutdowns across entire factory. Downtime: 4 hours. Cost: $1.2M.
Fix: Apply least privilege from day one. Even in development, scope policies to specific topics and actions.
With 64-bit tokens, collision probability rises to \(2.7 \times 10^{-10}\) – still low but 19 orders of magnitude higher than 128-bit. This is why modern IoT platforms use at least 128-bit random identifiers for access tokens, ensuring collision resistance even at billion-device scale.
Show code
viewof tokenBits = Inputs.range([32,256], {value:128,step:8,label:"Token bit length"})viewof activeTokensExp = Inputs.range([2,12], {value:5,step:1,label:"Active tokens (10^n)"})activeTokens =Math.pow(10, activeTokensExp)tokenSpace =Math.pow(2, tokenBits)exponent =-(Math.pow(activeTokens,2)) / (2* tokenSpace)collisionProb = exponent >-700?1-Math.exp(exponent) :-exponenthtml`<div style="background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 8px; padding: 16px; margin: 10px 0; font-family: system-ui, sans-serif;"><h4 style="margin-top:0; color: #2C3E50;">Token Collision Probability Calculator</h4><table style="width:100%; border-collapse: collapse;"><tr><td style="padding:4px 8px; font-weight:bold;">Token length:</td><td>${tokenBits} bits</td></tr><tr><td style="padding:4px 8px; font-weight:bold;">Token space (n):</td><td>2<sup>${tokenBits}</sup> = ${tokenSpace.toExponential(2)}</td></tr><tr><td style="padding:4px 8px; font-weight:bold;">Active tokens (k):</td><td>${activeTokens.toLocaleString()} (10<sup>${activeTokensExp}</sup>)</td></tr><tr><td style="padding:4px 8px; font-weight:bold;">Collision probability:</td><td style="color: ${collisionProb <1e-15?'#16A085': collisionProb <1e-6?'#E67E22':'#E74C3C'}; font-weight: bold;">${collisionProb <1e-300?"< 10⁻³⁰⁰ (effectively zero)": collisionProb.toExponential(2)}</td></tr><tr><td style="padding:4px 8px; font-weight:bold;">Assessment:</td><td>${collisionProb <1e-15?"Safe -- collision is astronomically unlikely": collisionProb <1e-6?"Caution -- consider longer tokens for production":"Unsafe -- high collision risk, use longer tokens"}</td></tr></table><p style="font-size: 0.85em; color: #7F8C8D; margin-bottom: 0;">Adjust the sliders to explore how token bit length and fleet size affect collision probability using the birthday paradox formula P(n,k) ≈ 1 - e<sup>-k²/2n</sup>.</p></div>`
Try It Yourself: Design AWS IoT Policy for Multi-Tenant Fleet
Create AWS IoT Core policies ensuring each customer can ONLY access their own vehicles in a fleet management system.
Scenario: 10,000 vehicles across 50 customers. Thing naming: vehicle-{customer_id}-{vehicle_num}
Exercise Steps:
Design Thing namespace to encode customer ownership
Write IoT policy using ${iot:Connection.Thing.ThingName} policy variable
Add explicit deny for cross-customer access attempts
Test scenarios: vehicle-acme-001 accessing own telemetry, trying to access vehicle-zeta-157
Matching Quiz: Match IoT Access Control Strategies
Ordering Quiz: Order IoT Access Control Deployment
Label the Diagram
💻 Code Challenge
10.8 Summary
This chapter covered access control for IoT:
RBAC: Role-based permissions for well-defined user categories, best for small-to-medium deployments
ABAC: Attribute-based policies for dynamic, context-aware access, scaling to multi-tenant platforms
OAuth 2.0: Device code flow for browserless authentication with token-based delegation
Certificate Identity: X.509 certificates provide strong, per-device cryptographic identity
Fleet Management: Automated provisioning, renewal, and revocation at scale using EST (RFC 7030)
Key Concepts
EST (Enrollment over Secure Transport): RFC 7030 protocol for automated X.509 certificate enrollment and renewal over HTTPS; enables large-scale IoT fleet certificate lifecycle management
Secure Element: A tamper-resistant hardware module (ATECC608A, TPM 2.0) that stores cryptographic keys and performs operations without exposing the key material to the host MCU
Device Provisioning: The process of loading a unique identity (certificate, key pair) onto a device during manufacturing or first boot; establishes the root of trust for all subsequent authentication
Certificate Revocation List (CRL): A list of revoked certificates published by the CA; devices and servers check this list to verify certificates have not been revoked
OCSP (Online Certificate Status Protocol): A protocol for real-time certificate revocation checking; more current than CRL but requires connectivity to the CA’s OCSP responder
Fleet Management System: Software that tracks all enrolled devices, manages their certificates, pushes OTA updates, and handles device decommissioning at scale
Zero-Touch Provisioning: Automated device onboarding where devices authenticate to a provisioning service at first boot and receive their operational credentials without human intervention
In 60 Seconds
IoT access control at scale requires automated certificate provisioning using EST protocol, hardware-backed device identity through X.509 certificates stored in secure elements, and fleet management systems that can revoke individual compromised devices without disrupting the other thousands of devices in the deployment.
10.9 Knowledge Check
Quiz: Access Control for IoT
Common Pitfalls
1. Provisioning Keys in Firmware Instead of Secure Elements
Embedding device private keys in firmware means anyone who extracts the binary can clone the device’s identity. Always generate the key pair inside a secure element (ATECC608A, TPM) where the private key never leaves the hardware boundary.
2. Not Implementing CRL or OCSP Checking
Accepting certificates without checking revocation status means a revoked device (compromised or decommissioned) can continue authenticating indefinitely. Always check CRL or OCSP for certificates in the authentication path.
3. Planning Certificate Renewal Only at Expiry
Waiting until a certificate expires to renew it risks a renewal failure leaving the device permanently unable to authenticate. Start renewal 90 days before expiry, retry automatically, and maintain a recovery channel (factory reset, out-of-band rekey) for devices that miss renewal.
4. Granting All Devices the Same Permissions Regardless of Type
A weather sensor and a motorized valve actuator both belong to the same IoT deployment but should never have the same permissions. Define device type-specific roles and restrict each device type to only the APIs and topics it legitimately needs to operate.
10.10 What’s Next
The next chapter explores Network Segmentation including VLANs, firewall rules, and micro-segmentation strategies for isolating IoT devices from critical infrastructure.