TapAuth is my Raspberry Pi NFC attendance and reservation system for the Asia Pacific College School of Engineering AIRHub. Version 1.1.2 is the current release: local-first card registration with durable offline recognition and optional MySQL/Firebase reconciliation. The name of a checkout folder does not define the product; this repository, application, and archive are TapAuth.
I started this as a straightforward tap-in and tap-out kiosk. Then I thought about what happens when the internet drops, MySQL restarts, or a newly registered card is tapped again immediately. That changed the project: the Pi now recognizes cards from its own durable registry first, keeps normal kiosk interactions fast, and reconciles data with MySQL and Firebase when those services are available.
- Detects whether a registered NFC card should check in or check out.
- Lets an unknown card register through a short, tap-bound session.
- Keeps registered cards recognizable without depending on MySQL for every tap.
- Supports 3D printing requests and teacher appointments.
- Shows the latest 25 activity records, with a compact See more view.
- Provides a private student and reservation management page.
- Mirrors safe activity data to Firebase without exposing NFC identifiers.
- Runs without a frontend build step: Flask, Python, HTML, CSS, and JavaScript.
Oh! On card registration, saving a student once is not enough if the next lookup depends entirely on a database connection. TapAuth stores a private copy at data/registered_cards.json on the Pi. The write is atomic, a backup is kept, and the directory is ignored by Git.
The tap flow is:
NFC card
|
v
Local card registry ---- recognized immediately
|
+---- MySQL available? ---- sync student and attendance data
|
+---- Firebase available? - copy approved private/public records
MySQL remains the main operational database. The local registry is the recognition fallback, not a public student database. Firebase is an optional remote copy and public-safe activity source.
The browser preview uses simulated taps and local browser storage:
python -m http.server 4173Open http://127.0.0.1:4173.
The terminal output is the ordinary Python server log; a successful start includes:
Serving HTTP on 0.0.0.0 port 4173 (http://0.0.0.0:4173/) ...
For the real NFC flow, run the Flask application on a Raspberry Pi with an ACR122U reader.
You need Raspberry Pi OS, an ACR122U USB NFC reader, and internet access for the first installation. Firebase is optional.
git clone https://github.com/devkyato/TapAuth.git
cd TapAuth
cp .env.example .env
nano .env
bash scripts/setup_raspberry_pi.shThe setup script installs MariaDB, Python dependencies, libnfc, reader permissions, the airhub.service systemd unit, and Chromium kiosk startup.
After setup:
- Kiosk:
http://127.0.0.1:5000/ - Student management:
http://127.0.0.1:5000/admin - System status:
http://127.0.0.1:5000/system_status
Copy .env.example to .env. At minimum, replace these values:
AIRHUB_DB_USER=airhub_app
AIRHUB_DB_PASSWORD=replace-with-a-strong-password
AIRHUB_DB_NAME=airhub_db
TAPAUTH_ADMIN_CODE=replace-with-a-private-admin-codeTAPAUTH_REGISTRY_PATH may be left blank to use data/registered_cards.json.
To enable Firebase:
AIRHUB_FIREBASE_ENABLED=true
AIRHUB_FIREBASE_MODE=realtime_db
AIRHUB_FIREBASE_DATABASE_URL=https://your-project-default-rtdb.region.firebasedatabase.app
AIRHUB_FIREBASE_DATABASE_SECRET=your-server-side-database-secret
AIRHUB_FIREBASE_PROJECT_ID=your-project-id
AIRHUB_FIREBASE_ROOT=tapauthThe Firebase browser apiKey identifies the web app; it is not an administrator secret. Never commit .env, database secrets, service-account files, student records, or NFC UIDs.
I treated Firebase as a synchronized view, not as a requirement for tapping a card. This keeps the kiosk usable on the local network even when cloud access is interrupted.
npm install -g firebase-tools
firebase login --no-localhost
firebase use your-project-id
firebase deploy --only database,hostingTo copy existing MySQL records:
source .venv/bin/activate
python scripts/sync_realtime_db.pyPrivate users and reservations live below tapauth/users and tapauth/reservations. Only sanitized event and timing fields under tapauth/logs are publicly readable.
cd ~/TapAuth
git pull --ff-only origin main
bash scripts/update_pi_from_github.sh
sudo systemctl restart airhub.service
sudo systemctl status airhub.serviceThe update script also reconciles MySQL students with the local card registry. If MySQL is temporarily unavailable, the existing local registry stays usable.
bash scripts/diagnose_nfc.sh
sudo systemctl restart airhub.service
journalctl -u airhub.service -fTapAuth retries disconnected readers automatically. The setup disables pcscd because it can claim the ACR122U before libnfc.
| Path | Purpose |
|---|---|
app.py |
Flask API, tap sessions, registration, attendance, and admin routes |
scanner.py |
ACR122U reader loop and reconnection |
nfc_utils.py |
Stable UID normalization |
local_registry.py |
Durable card-recognition fallback |
database.py |
MySQL students, logs, reservations, and sync queue |
firebase_adapter.py |
Firebase Realtime Database writer |
index.html, script.js |
Kiosk and reservation interface |
templates/admin.html |
Local management page |
hosting/ |
Firebase-hosted public activity page |
scripts/ |
Setup, update, sync, diagnostics, backup, and migration |
tests/ |
Registration, privacy, UID, registry, and activity tests |
For a deeper technical reference, see ARCHITECTURE.md. For task-oriented setup, operations, security, and release notes, use the documentation index.
python -m compileall -q .
node --check script.js
node --check hosting/app.js
node --check hosting/firebase-config.js
python -m json.tool firebase.json
python -m json.tool database.rules.json
python -m unittest discover -s tests -vTapAuth is a personal, deployment-oriented Raspberry Pi application, not a hosted service or a source package. Real NFC workflows require an ACR122U and the permissions and services installed by the setup script. MySQL remains the main operational database; the local registry only keeps card recognition available, and Firebase is optional. Browser preview storage and simulated taps do not reproduce hardware, service outages, or production data handling. Keep backups and test updates on the target Pi.
If you use this software in research or teaching, please cite the Zenodo archive / this repository:
@dev.mako (devkyato). (2026). TapAuth: Raspberry Pi NFC attendance and reservation kiosk with local-first registration (Version 1.1.2).
See CITATION.cff for machine-readable metadata.
- Attendance kiosks for schools and laboratories.
- Local-first NFC card registration and recognition.
- Maker-space equipment and appointment reservations.
- Raspberry Pi kiosk deployments with optional service reconciliation.
| Project | Role |
|---|---|
| OpenNet | Typed ONP/1 messaging for ESP32, Raspberry Pi, and backends |
| Datary | Local-first laboratory for reproducible program and simulation evidence |
| Relay | Timing-risk source review for control programs |
| Lowpack | Local-first, application-aware lossless packing |
| Custom Arduino Libraries | Non-blocking LED and digital-output patterns |
| Arduino Programs Guide | Safety-first, compile-checked Arduino Uno course |
This is a personal project, but focused issues and pull requests are welcome.
Source, configuration, NFC identifiers, and student data need different
handling: never commit .env, credentials, database exports, service-account
files, records, or UIDs. Please read CONTRIBUTING.md, use
SUPPORT.md for diagnostics, and report security problems
privately through SECURITY.md.
TapAuth is available under the MIT License.
