Worked example: With 5 runs and per-run times of 4 min setup, 6 min execution, and 3 min review, total lab time is \(5\times(4+6+3)=65\) minutes. This prevents under-scoping and helps schedule complete experimental cycles.
Show code
viewof labRuns = Inputs.range([1,20], {value:5,step:1,label:"Number of runs"})viewof labSetup = Inputs.range([1,15], {value:4,step:1,label:"Setup time (min)"})viewof labExec = Inputs.range([1,30], {value:6,step:1,label:"Execution time (min)"})viewof labReview = Inputs.range([1,15], {value:3,step:1,label:"Review time (min)"})
By completing this implementation, you will be able to:
Implement the full authentication flow from card scan to access decision
Build authorization logic with role-based access control
Create comprehensive audit logging for security forensics
Test multiple security scenarios including lockouts and disabled accounts
Understand the relationship between real-world systems and this lab implementation
For Beginners: Lab: Access Control Implementation
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.
Copy this complete code into the Wokwi editor. This includes all functions from the setup plus the core authentication, authorization, and feedback logic. Paste all sections below in order into a single file.
18.2.1 Includes, Pin Definitions, and Data Structures
/* * Secure IoT Access Control System * Demonstrates: RFID-style authentication, role-based access control, * lockout policies, and comprehensive audit logging */#include <Arduino.h>// Pin definitionsconstint LED_ACCESS_GRANTED =2;// Green LEDconstint LED_ACCESS_DENIED =4;// Red LEDconstint LED_SYSTEM_STATUS =5;// Yellow LEDconstint LED_ADMIN_MODE =18;// Blue LEDconstint BUZZER_PIN =19;constint BUTTON_SELECT =15;constint BUTTON_ACCESS =16;// Access levels and credential structureenum AccessLevel { ACCESS_NONE=0, ACCESS_GUEST=1, ACCESS_USER=2, ACCESS_ADMIN=3};struct UserCredential {constchar* cardId;constchar* userName; AccessLevel accessLevel;bool isActive;};
18.2.2 Credential Database and Security Configuration
UserCredential* authenticateCard(constchar* cardId){for(int i =0; i < NUM_USERS; i++)if(constantTimeCompare(cardId, userDatabase[i].cardId))return&userDatabase[i];return NULL;}bool constantTimeCompare(constchar* a,constchar* b){size_t lenA = strlen(a), lenB = strlen(b);size_t maxLen =(lenA > lenB)? lenA : lenB;volatileint result =0;for(size_t i =0; i < maxLen; i++){char charA =(i < lenA)? a[i]:0;char charB =(i < lenB)? b[i]:0; result |= charA ^ charB;} result |=(lenA != lenB);return(result ==0);}bool authorizeAccess(AccessLevel userLevel, AccessLevel required){return userLevel >= required;}
18.2.6 Access Request Processing
This is the core logic that combines authentication (identity check), authorization (permission check), and lockout enforcement into a single access decision.
18.3.2 Scenario B: Valid User - Insufficient Privileges
CARD 1
ZONE 2
Expected Results:
Charlie User (USER level) trying Server Room (needs ADMIN)
Red LED flashes
Low error tones
“ACCESS DENIED - Insufficient Privileges” message
Authentication PASSED but Authorization FAILED
18.3.3 Scenario C: Guest Access to Public Area
CARD 2
ZONE 0
Expected Results:
Eve Guest accessing Public Lobby
Green LED on (no blue - not admin)
Success tones
“ACCESS GRANTED” message
18.3.4 Scenario D: Unknown Card (Brute Force Prevention)
CARD 4
ZONE 0
ZONE 0
ZONE 0
Expected Results after 3 failed attempts:
Yellow LED blinking
System LOCKED for 60 seconds
“Possible brute force attack detected” message
18.3.5 Scenario E: Disabled Account
CARD 3
ZONE 0
Expected Results:
Frank Former (disabled account)
Red LED flashes
“Account DISABLED” message
18.4 Security Concepts Demonstrated
Concept
Implementation
Real-World Application
Token-Based Auth
RFID card IDs matched against database
Physical access cards, API keys, JWT tokens
Role-Based Access Control
GUEST < USER < ADMIN hierarchy
Corporate access levels, AWS IAM roles
Account Lockout
60s lockout after 3 failures, escalating
Windows account lockout, banking apps
Disabled Accounts
Active flag checked during authentication
Employee offboarding, compromised accounts
Constant-Time Compare
XOR comparison prevents timing attacks
Secure password validation, crypto libraries
Audit Logging
Complete event trail with timestamps
SIEM systems, compliance logging
Separation of Concerns
Authentication separate from Authorization
OAuth 2.0 (AuthN) vs resource permissions (AuthZ)
Defense in Depth
Multiple checks: valid card, active account, sufficient level
Enterprise security architecture
18.5 Challenge Exercises
Challenge 1: Add Time-Based Access Control
Modify the system so certain zones are only accessible during “business hours” (simulate with a time window): - Server Room: Only accessible 9 AM - 5 PM - After hours, even admins need a special override code - Log all after-hours access attempts
Challenge 2: Implement Two-Person Rule
For high-security zones (Control Center), require two different admin cards within 30 seconds: 1. First admin presents card 2. System prompts “Waiting for second administrator…” 3. Second admin presents different card within time limit 4. Both must be admin level 5. If timeout or same card, deny access
Challenge 3: Add Temporary Access Passes
Implement visitor passes with expiration: - Create a new ACCESS_VISITOR level - Visitor cards expire after a set time (e.g., 8 hours from first use) - Track first-use timestamp per card - Automatically disable expired passes
Challenge 4: Implement Anti-Passback
Prevent “tailgating” by tracking entry/exit: - Users must exit a zone before re-entering - If card used for entry without previous exit, deny access - Track current zone for each user - Alert on anti-passback violations
18.6 Connecting to Real-World Systems
Lab Implementation
Production Equivalent
RFID card IDs
Smart cards with cryptographic challenge-response
Hardcoded user database
LDAP/Active Directory integration
Serial monitor
Secure management API (TLS + client certificates)
LED indicators
Security Operations Center (SOC) dashboards
Buzzer alerts
SIEM integration, SMS/email notifications
Simple lockout
Adaptive authentication with risk scoring
Role hierarchy
Attribute-Based Access Control (ABAC)
Real-world systems these concepts apply to:
Corporate badge access (HID, SALTO)
Data center entry (biometric + card + PIN)
AWS IAM policies (principals, resources, actions)
Kubernetes RBAC (roles, bindings, service accounts)
Worked Example: Calculating Account Lockout Impact on User Experience
Scenario: Your smart building access control system has 3,000 employees. You need to choose appropriate lockout settings that balance security with user experience.
Step 1: Analyze Current Failed Login Patterns
Data from 30 days (before lockout policy):
Total login attempts: 450,000
Failed logins: 18,000 (4% failure rate)
Users with >3 failures: 427 users (14.2% of workforce)
Breakdown of failures:
1-2 failures: 2,100 users (70% - typos, forgotten passwords)
3-5 failures: 427 users (14.2% - legitimate users struggling)
6+ failures: 73 users (2.4% - suspicious, possible brute force)
Step 2: Calculate Lockout Impact
// Scenario A: Aggressive Lockout (3 attempts, 30 minutes)constint MAX_FAILED_ATTEMPTS =3;constunsignedlong LOCKOUT_DURATION_MS =1800000;// 30 minutesImpact Calculation: Users affected:427+73=500 users/month (16.7%) Average lockout time:30 minutes Productivity loss:500 users × 30 min =250 person-hours/month Help desk calls:500 calls/month × $15/call =$7,500/month User frustration: HIGH// Scenario B: Balanced Lockout (5 attempts, 15 minutes)constint MAX_FAILED_ATTEMPTS =5;constunsignedlong LOCKOUT_DURATION_MS =900000;// 15 minutesImpact Calculation: Users affected:73 users/month (2.4%) Average lockout time:15 minutes Productivity loss:73 × 15 min =18.25 person-hours/month Help desk calls:73 calls/month × $15/call =$1,095/month User frustration: LOW// Scenario C: Lenient (10 attempts, 60 minutes)constint MAX_FAILED_ATTEMPTS =10;constunsignedlong LOCKOUT_DURATION_MS =3600000;// 60 minutesImpact Calculation: Users affected:~15 users/month (0.5%) Security risk: Brute force attacks can try10 passwords Average lockout time:60 minutes Productivity loss:15 × 60 min =15 person-hours/month Help desk calls:15 calls/month × $15/call =$225/month Security posture: WEAK
Step 4: Measure Real-World Results After Implementation
After 30 days with escalating lockout (3 attempts, escalating):
Legitimate User Impact:
Users locked out: 127 (down from 500)
Average lockout: 1.8 minutes (down from 30)
Help desk calls: 127 × $15 = $1,905/month (73% reduction)
User satisfaction: 87% (was 62%)
Security Improvements:
Brute force attempts detected: 47
Accounts compromised: 0 (was 3 suspected)
Average attacker attempts before lockout: 3.2
Maximum attacker attempts: 8 (hit 5-minute cap)
ROI Calculation:
Cost savings: $7,500 - $1,905 = $5,595/month
Security incidents prevented: 3 compromises × $25,000 avg = $75,000
Annual ROI: $67,140 + $75,000 = $142,140
Key Decisions Made:
3-attempt threshold: Catches obvious attacks while allowing typos
Escalating duration: First lockout is short (1 min), grows with repeated failures
5-minute cap: Prevents excessive lockouts for confused legitimate users
30-second escalation steps: Gradual increase balances security and UX
Lesson Learned: Escalating lockouts provide better security than fixed timeouts while significantly improving user experience. The 73% reduction in help desk calls alone justified the implementation.
Interactive: Lockout Policy Impact Calculator
Use this calculator to explore how different lockout settings affect user experience and security costs for your deployment.
Decision Framework: Choosing RFID vs Biometric vs PIN Authentication
Choose the right authentication method based on your building’s security requirements and user population.
Factor
RFID Card
PIN Code
Fingerprint
Face Recognition
Security Level
Medium
Low
High
High
Cost per User
$3-8 (card)
$0
$15-30 (reader)
$50-200 (reader)
Speed
<1 second
3-5 seconds
1-2 seconds
1-3 seconds
User Acceptance
Very High (95%+)
High (85%)
Medium (70%)
Low (50%)
Hygiene Concerns
None
None
High (COVID)
None (contactless)
Lost/Stolen Risk
High (card theft)
Medium (shoulder surfing)
Low (can’t steal)
Low (can’t steal)
Works with Gloves
Yes
Yes
No
Yes
Privacy Concerns
Low
None
Medium (biometric data)
High (biometric + video)
Backup Method Required
Yes (lost cards)
No
Yes (injury, sweat)
Yes (poor lighting, masks)
ADA Compliance
Excellent
Good (audio prompts)
Fair (tactile aids)
Poor (blind users)
Use Case Recommendations:
Facility Type
Primary Method
Backup Method
Rationale
Office (low security)
RFID card
PIN code
Fast, cheap, high acceptance. PIN for lost cards.
Data Center (high security)
Fingerprint + RFID
PIN (admin override)
Two-factor: something you have + something you are.
Hospital (hygiene priority)
Face recognition
RFID card
No-touch for infection control. Card for masked staff.
Factory (gloves worn)
RFID card
Face recognition
Gloves prevent fingerprint. Face works with PPE.
Apartment Building (residents)
RFID fob + PIN
Mobile app (Bluetooth)
Low-cost. Residents unlikely to accept biometrics.
Decision Tree:
Q1: What is the security level required?
Low (office, apartments) → RFID card + PIN
High (data center, labs) → Continue to Q2
Q2: Are biometrics acceptable to users?
NO → Multi-factor RFID (card + PIN)
YES → Continue to Q3
Q3: Do users wear gloves or have hand injuries?
YES → Face recognition + RFID backup
NO → Fingerprint + RFID backup
Q4: Is contactless important (hygiene)?
YES → Face recognition or mobile app (Bluetooth)
NO → Fingerprint is most reliable biometric
Common Mistake: Choosing face recognition for “cool factor” without considering: - Privacy backlash (biometric data storage concerns) - Poor performance with masks, glasses, hats - High false rejection rate (5-10%) frustrates legitimate users - Expensive ($200+/reader vs $50 for RFID) - Requires backup method (adding cost and complexity)
Best Practice: Start with RFID + PIN (proven, cheap, high acceptance). Add biometrics only where security requirements justify the cost and user friction.
Common Mistake: Using strcmp() for Credential Comparison
Mistake: Using standard string comparison functions exposes your system to timing attacks.
Vulnerable Code:
// BAD: strcmp returns immediately on first mismatchUserCredential* authenticateCard(constchar* cardId){for(int i =0; i < NUM_USERS; i++){if(strcmp(cardId, userDatabase[i].cardId)==0){return&userDatabase[i];// FOUND!}}return NULL;// Not found}
Attack Scenario:
An attacker measures response times for different card IDs:
Attempt 1: cardId = "AAAA_ADMIN_001"
Response time: 0.23 ms (fast - mismatched at first character 'A' vs 'R')
Attempt 2: cardId = "RFID_AAAA_001"
Response time: 0.51 ms (slower - matched first 5 chars "RFID_")
Attempt 3: cardId = "RFID_ADMIN_001"
Response time: 1.34 ms (even slower - matched 14 chars!)
By measuring timing differences, the attacker deduces: - Card IDs start with “RFID_” - Valid format is “RFID_ADMIN_NNN” - Can guess valid card IDs character-by-character
The loop exits on the FIRST mismatch. If strings match for 5 characters, the loop runs 5 iterations. If they match for 10 characters, it runs 10 iterations. This timing difference leaks information!
Secure Implementation (from lab code):
// GOOD: Constant-time comparisonbool constantTimeCompare(constchar* a,constchar* b){size_t lenA = strlen(a);size_t lenB = strlen(b);// Always process maximum length (timing independent of input)size_t maxLen =(lenA > lenB)? lenA : lenB;volatileint result =0;// volatile prevents compiler optimizationfor(size_t i =0; i < maxLen; i++){char charA =(i < lenA)? a[i]:0;char charB =(i < lenB)? b[i]:0; result |= charA ^ charB;// XOR accumulates differences}// Also check lengths match result |=(lenA != lenB);return(result ==0);// True only if ALL bits matched}
Why This Works:
Fixed iterations: Always loops maxLen times, regardless of where mismatch occurs
No early exit: Cannot break out of loop early (timing constant)
XOR accumulation: Differences accumulate in result, but timing doesn’t reveal WHICH characters differ
Volatile keyword: Prevents compiler from optimizing away comparisons
Timing Test Results:
Input Comparison | strcmp() Time | constantTimeCompare() Time
------------------------------|---------------|---------------------------
"AAAA" vs "RFID_ADMIN_001" | 0.18 ms | 1.42 ms
"RFID" vs "RFID_ADMIN_001" | 0.43 ms | 1.42 ms
"RFID_ADMIN_00" vs "RFID_ADMIN_001" | 1.21 ms | 1.42 ms
"RFID_ADMIN_001" vs "RFID_ADMIN_001" | 1.34 ms | 1.42 ms
Standard deviation (strcmp): 0.47 ms (HUGE variance)
Standard deviation (constantTime): 0.03 ms (negligible)
Real-World Impact: In 2015, timing attacks were used to extract PayPal API keys character-by-character. The attack took 2 hours to extract a 32-character key by measuring response times. Constant-time comparison would have prevented this entirely.
Testing Checklist:
Matching Quiz: Match Basic Lab Components to Roles
Ordering Quiz: Order the Basic Authentication Lab Setup
Label the Diagram
💻 Code Challenge
18.7 Summary
By completing this lab, you have:
Implemented token-based authentication using simulated RFID cards
Built a role-based access control system with three distinct permission levels
Applied account lockout policies with escalating timeouts to prevent brute force attacks
Created comprehensive audit logging for security forensics
Designed intuitive feedback systems using LEDs and audio
Understood the critical difference between authentication and authorization
Key Takeaway
Authentication answers “Who are you?” while Authorization answers “What can you do?”
The audit log ties it all together for the third “A” - Accounting - so you can investigate incidents after the fact.
18.8 Knowledge Check
Quiz: Lab: Access Control Implementation
Common Pitfalls
1. Storing Passwords as MD5 or SHA256 Hashes Without Salt
MD5 and SHA256 are cryptographic hash functions, not password hashing functions. They are fast (enabling brute force) and lack salt (enabling precomputed rainbow table attacks). Always use bcrypt, scrypt, or Argon2 for password storage.
2. Returning Detailed Error Messages on Authentication Failure
Returning “User not found” vs “Password incorrect” tells attackers which usernames are valid. Always return the same generic error (“Invalid credentials”) regardless of whether the username or password was wrong.
3. Not Implementing the Authorization Check in Middleware
Adding authorization checks directly inside each route handler leads to inconsistent enforcement — it’s easy to forget to add the check in a new handler. Implement authorization as Express middleware (or equivalent) that runs before every protected handler.
4. Using String Comparison Instead of Timing-Safe Functions for Token Verification
Standard string equality comparison (===) short-circuits on the first mismatch, creating a timing side-channel that can reveal how many characters of a guessed token match. Use crypto.timingSafeEqual() for all security-sensitive comparisons.
bcrypt: A password hashing function with built-in salt and adjustable cost factor; the standard for securely storing user passwords in databases
Password Salt: A random value added to the password before hashing; ensures that identical passwords produce different hashes, preventing rainbow table attacks
Protected Route: An API endpoint that requires a valid authentication token; implemented as middleware that rejects unauthorized requests before they reach the handler
Role Assignment: The process of associating a user or device with one or more roles that define their permissions; typically stored in the user record or a separate roles table
Permission Check: A validation that the authenticated principal’s role includes permission to perform the requested operation on the target resource
Timing-Safe Comparison: Using constant-time comparison functions for password verification to prevent timing attacks that can reveal whether a password attempt was close to correct
Token Expiry: The time-to-live value embedded in authentication tokens; balances security (short-lived = less exposure if stolen) against usability (long-lived = fewer re-logins)
In 60 Seconds
This hands-on lab builds a working RBAC system from scratch — implementing user authentication with hashed passwords, role assignment, permission checking middleware, and protected API endpoints — giving you practical experience with the security code patterns used in real IoT platforms.