DEV Community

Cover image for ๐Ÿฐ Castle of Keys: API-First Access Control in a Physical-Digital Game
James Moro
James Moro Subscriber

Posted on

32 7 6 7 6

๐Ÿฐ Castle of Keys: API-First Access Control in a Physical-Digital Game

This is a submission for the Permit.io Authorization Challenge: API-First Authorization Reimagined

Table of Contents

What I Built

Castle of Keys is an interactive, real-world access control game inspired by medieval castles and powered by externalized authorization using Permit.io.

Players assume roles like King, Cook, or Servant and attempt to access different levels of a castle. Access is controlled by external policies โ€” not hardcoded logic.


๐Ÿ”„ How It Works (Step-by-Step Flow)

  1. The player presents an RFID card to the reader connected to the ESP32.
  2. The ESP32 reads the UID and sends a request to proxy.php, including the UID and desired action (e.g., access_floor_2).
  3. The proxy.php script securely forwards the request to the Permit.io API using a private token.
  4. Permit.io returns whether the access is allowed ("allow": true) or not.
  5. The ESP32 interprets the response and activates the corresponding LED:
    • โœ… Green = Access Granted
    • โŒ Red = Access Denied
  6. In parallel, the ESP32 sends the log to log.php โ€” used for visual display or debugging in the web interface.

โš ๏ธ Note: log.php is not required for Permit.io to function. Itโ€™s used to display access attempts inside the game UI.


๐ŸŽฎ Demo

๐Ÿ‘‰ Watch the full walkthrough demo (Web + Hardware):

๐ŸŽฎ Or test the web version (no hardware required): Try the Castle of Keys (Web Demo)


๐Ÿ’ก My Journey

This project started as an idea to bring access control to life through gamification. I wanted to create something more than just a UI button or a permission table โ€” something tangible, physical, and interactive. Thatโ€™s why I decided to integrate real hardware like RFID readers and, soon, biometric sensors, to make the experience both fun and immersive.


๐Ÿ” API-First Authorization

Below is the actual .ino code running on my ESP32. It reads an RFID card using the RC522 module, sends the UID to a secure PHP proxy, and receives a real-time authorization decision from Permit.io.

๐Ÿ”Œ ESP32 Code (Arduino)

#include <WiFi.h>
#include <HTTPClient.h>
#include <SPI.h>
#include <MFRC522.h>

const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";


const char* permitUrl = "https://example.com/api/proxy.php"; // your private endpoint
const char* logUrl = "https://example.com/app/log.php";

#define RST_PIN 22
#define SS_PIN  21

MFRC522 rfid(SS_PIN, RST_PIN);

void setup() {
  Serial.begin(115200);
  SPI.begin();
  rfid.PCD_Init();

  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected!");
}

void loop() {
  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) {
    return;
  }

  String uid = "";
  for (byte i = 0; i < rfid.uid.size; i++) {
    uid += String(rfid.uid.uidByte[i], HEX);
  }
  uid.toUpperCase();

  Serial.print("Card detected: ");
  Serial.println(uid);

  // Make Permit.io authorization request
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(permitUrl);
    http.addHeader("Content-Type", "application/json");

    String payload = "{\"user\":{\"key\":\"" + uid + "\"},\"action\":\"" + action + "\",\"resource\":{\"type\":\"document\",\"tenant\":\"devs\"},\"context\":{}}";

    int httpResponseCode = http.POST(payload);

    if (httpResponseCode > 0) {
      String response = http.getString();
      Serial.println("Permit.io response: " + response);

      if (response.indexOf("\"allow\":true") > 0) {
        Serial.println("โœ… Access granted");
        accessGranted = true;
        // digitalWrite(GREEN_LED, HIGH);
      } else {
        Serial.println("โŒ Access denied");
        // digitalWrite(RED_LED, HIGH);
      }

    } else {
      Serial.print("Error on sending request: ");
      Serial.println(httpResponseCode);
    }

    http.end();

    // Send access log
    HTTPClient logHttp;
    logHttp.begin(logUrl);
    logHttp.addHeader("Content-Type", "application/json");

    String logPayload = "{\"uid\":\"" + uid + "\",\"action\":\"" + action + "\",\"status\":\"" + (accessGranted ? "granted" : "denied") + "\"}";
    logHttp.POST(logPayload);
    logHttp.end();
  }

  delay(3000); // Prevent repeated scans
}
Enter fullscreen mode Exit fullscreen mode

PHP Proxy for Permit.io (ESP32 Integration)

To keep your Permit.io API key safe, I created a simple proxy.php file. The ESP32 sends a request to this PHP script instead of calling Permit.io directly.

Hereโ€™s the full code:

<?php
// proxy.php - Receives data from ESP32 and checks permission via Permit.io

// Read the incoming JSON from ESP32
$body = file_get_contents('php://input');
$data = json_decode($body, true);

// Prepare the payload for Permit.io
$payload = json_encode([
  "user" => [
    "key" => $data['user']  // UID from RFID card
  ],
  "action" => $data['action'], // Example: "access_floor_1"
  "resource" => [
    "type" => "document",   // Replace with your configured resource type
    "tenant" => "devs"      // Tenant ID (if applicable)
  ],
  "context" => new stdClass() // Additional context (empty for now)
]);

// Send the request to Permit.io
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://api.permit.io/v2/allowed");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  "Authorization: Bearer YOUR_PERMIT_API_KEY", // Replace with your Permit.io API key
  "Content-Type: application/json"
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Return the result back to the ESP32
http_response_code($http_code);
echo $response;
Enter fullscreen mode Exit fullscreen mode

โœ… Conclusion

This project shows how easy it is to integrate real-world hardware with Permit.io. With just a few lines of code and external policies, you can control access securely โ€” without hardcoding anything.

Redis image

Short-term memory for fasterโ€จAI agents

AI agents struggle with latency and context switching. Redis fixes it with a fast, in-memory layer for short-term contextโ€”plus native support for vectors and semi-structured data to keep real-time workflows on track.

Start building

Top comments (20)

Collapse
 
nevodavid profile image
Nevo David โ€ข

This is actually cool, I like seeing hardware hooked up to APIs like that - makes me wanna mess around with RFID and build something myself. You think people will ever trust this kind of access control as much as the old-school key and lock?

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;)

Basic RFID can be cloned, sure โ€” but with encryption, biometrics, and cloud validation, it gets a lot more secure. Many modern locks use RFID nowadays, and while safer setups tend to cost more, they can offer a good level of trust, depending on how itโ€™s done.

Collapse
 
davinceleecode profile image
davinceleecode โ€ข

This project is impressive and truly one of a kind. It's clear you put a lot of effort into itโ€”amazing work!

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;) I had a blast building itโ€”happy you liked it!

Collapse
 
dev_kiran profile image
Kiran Naragund โ€ข

Awesome โšก

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;)

Collapse
 
bridget_amana profile image
Bridget Amana โ€ข

This is so cool

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;)

Collapse
 
nadeem_zia_257af7e986ffc6 profile image
nadeem zia โ€ข

Amazing work

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;)

Collapse
 
aidityasadhakim profile image
Aidityas Adhakim โ€ข

Very neat!

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;)

Collapse
 
therealfredp3d profile image
Frederick Pellerin โ€ข

That's the most nerdy project I've seen. Wow... Loving it!

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;) It was a fun project to build and learn from โ€” totally worth the time!

Collapse
 
zealai profile image
Zeal AI โ€ข

Amazing product!!!

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;)

Collapse
 
adamson_keyy_3b37b1080c66 profile image
Adamson Keyy โ€ข

Cool

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;)

Collapse
 
aleksandr_heinlaid_8f4995 profile image
Aleksandr Heinlaid โ€ข โ€ข Edited

Nice project! really like the mix of physical access with API-based permissions - feels like a solid base for real-world use. The castle theme makes it more fun and relatable too ;)

Collapse
 
jamesrmoro profile image
James Moro โ€ข

Thanks ;) The idea was to mix reality with a fun twist โ€” I'm glad you liked the castle theme!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

Dev Diairies image

User Feedback & The Pivot That Saved The Project

๐Ÿ”ฅ Check out Episode 3 of Dev Diairies, following a successful Hackathon project turned startup.

Watch full video ๐ŸŽฅ

๐Ÿ‘‹ Kindness is contagious

Dive into this thoughtful piece, beloved in the supportive DEV Community. Coders of every background are invited to share and elevate our collective know-how.

A sincere "thank you" can brighten someone's dayโ€”leave your appreciation below!

On DEV, sharing knowledge smooths our journey and tightens our community bonds. Enjoyed this? A quick thank you to the author is hugely appreciated.

Okay