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)
- The player presents an RFID card to the reader connected to the ESP32.
- The ESP32 reads the UID and sends a request to
proxy.php
, including the UID and desired action (e.g.,access_floor_2
). - The
proxy.php
script securely forwards the request to the Permit.io API using a private token. - Permit.io returns whether the access is allowed (
"allow": true
) or not. - The ESP32 interprets the response and activates the corresponding LED:
- โ Green = Access Granted
- โ Red = Access Denied
- 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
}
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;
โ 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.
Top comments (21)
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?
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.
Awesome โก
Thanks ;)
Very neat!
Thanks ;)
This project is impressive and truly one of a kind. It's clear you put a lot of effort into itโamazing work!
Thanks ;) I had a blast building itโhappy you liked it!
Amazing work
Thanks ;)
That's the most nerdy project I've seen. Wow... Loving it!
Thanks ;) It was a fun project to build and learn from โ totally worth the time!
This is so cool
Thanks ;)
Amazing product!!!
Thanks ;)
Cool
Thanks ;)
Thereโs a way to cloud this whole project free by means of natural nerve-learning cloning . This kind of access encrypts even the clone validation itself . The resultant contents are typically saved as disk image semi-coded files . Cryptanalysis cannot โbypassโ nonlinear aspects of your code(s) . They say AESโs developers actually managed to offer the design of the round transformation amenable to clear-clone analysis.The aim of this latter algorithmization is a process of the wide trail strategy implementation in a round Complex Function without its separation into linear and nonlinear parts.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.