How one more question about proxy attendance pushed me to add another layer of trust to my attendance system.*
The QR Code Was Already Dynamic
When I started building my anti-proxy attendance system, I knew a normal QR code wasn't enough.
If a teacher displays the same QR code for an entire class, someone can simply take a screenshot and send it to a friend.
So I designed the attendance flow around dynamically changing QR codes.
The QR token has a short lifetime.
The backend validates it.
An old screenshot shouldn't remain useful indefinitely.
Problem solved.
Or so I thought.
Then I Asked One More Question
What if the student doesn't share the QR code?
What if they share their account instead?
Imagine this:
CLASSROOM
Student A
│
├── Valid account
├── Valid device
└── Scans QR
│
▼
Attendance
HOSTEL
Student B
│
├── Gets Student A's credentials
├── Logs into another phone
└── Attempts attendance
The QR could be perfectly valid.
The credentials could be perfectly valid.
The request could be authenticated.
And the attendance could still be fraudulent.
That was the moment I realized:
I wasn't only solving a QR problem anymore.
I was solving an identity problem.
Authentication Isn't Device Trust
A login system answers:
Who is this user?
But I wanted the attendance system to have another piece of information:
Is this request coming from the device associated with this account?
So I added device-bound authentication as another layer in the verification process.
The basic idea:
Student Account
│
▼
Trusted Device
│
▼
Attendance Request
│
▼
Backend Verification
The device association becomes another signal the backend can use before accepting attendance.
The Device Registration Flow
The simplified architecture looks like this:
First Login
│
▼
Generate / Retrieve Device ID
│
▼
Associate Device With Account
│
▼
Store Device Association
│
▼
Future Attendance Request
│
▼
Backend Verification
│
├──────────────┐
│ │
Match Mismatch
│ │
▼ ▼
Continue Reject
The important part is where the decision happens.
The backend decides.
The client can send a device identifier, but the client shouldn't be trusted to decide whether that identifier is legitimate.
One Account. One Trusted Device.
For the relevant student flow, my implementation maintains a strict one-to-one device association.
The project uses a persistent identifier:
uba_emergency_device_id
to maintain that association.
Conceptually:
Student A
│
└── Device A ✅
But:
Student A
│
├── Device A ✅
└── Device B ❌
The important part is that knowing the correct credentials doesn't automatically make a new device trusted.
Where It Fits Into the Attendance Pipeline
Device verification doesn't replace the dynamic QR system.
It sits alongside it.
The complete flow becomes:
Attendance Request
│
▼
User Authentication
│
▼
Dynamic QR Validation
│
▼
Device Verification
│
▼
Backend Validation
│
▼
Attendance Recorded
Each layer handles a different problem.
Dynamic QR
Reduces the usefulness of screenshots and previously captured QR codes.
Authentication
Establishes the student's account identity.
Device verification
Makes casual account sharing across devices harder.
Backend validation
Keeps the final decision outside the client.
But There Is No Magic Device ID
This is where I want to be careful with the security claims.
A client-side device identifier isn't an unbreakable hardware identity.
Depending on the environment, a determined attacker may be able to manipulate or reset it.
So I don't describe this system as:
"A device ID that makes proxy attendance impossible."
That's not accurate.
Instead, the goal is:
Make casual proxy attendance significantly harder without making legitimate attendance painful.
That's a much more realistic security objective.
The Problem With Locking Devices
As soon as you associate an account with a device, you create another problem.
What happens when the legitimate student:
- Gets a new phone?
- Loses their phone?
- Factory-resets it?
- Clears their browser storage?
- Needs to replace a damaged device?
A security mechanism without a recovery mechanism quickly becomes a usability problem.
This means device binding isn't just:
if deviceId === registeredDeviceId
allow
else
reject
The real system also needs to think about:
Device Change
│
├── Legitimate?
│
├── Suspicious?
│
└── Recovery Required?
That's where the engineering gets interesting.
Security vs Usability
Every additional security layer creates friction.
More security can mean:
More protection
but also:
More ways to block legitimate users.
For this system, I think about the balance as:
SECURITY
×
USABILITY
×
RECOVERABILITY
All three matter.
A system that rejects every suspicious request but locks legitimate students out isn't a good attendance system.
A system that is incredibly convenient but trusts every request isn't much of an anti-proxy system either.
What This Actually Protects Against
Device binding can help reduce:
- Credential sharing
- Casual multi-device access
- Basic account-based proxy attendance
- Repeated use of one student's account from another device
It does not magically protect against every possible attacker.
It doesn't eliminate:
- Compromised devices
- Sophisticated manipulation
- Device identifier tampering
- Someone physically using the registered device
That's okay.
The goal is to address the threat model that actually matters for the project.
Ordinary proxy attendance.
Not a security research laboratory.
The Bigger Lesson
When I started this project, I thought preventing proxy attendance was mostly about QR codes.
Then I realized it wasn't.
The QR answers something about the attendance session.
Authentication answers something about the student.
Device verification gives another signal about the device making the request.
Backend validation brings those signals together.
The result isn't one perfect security mechanism.
It's several imperfect mechanisms working together.
And that has probably been one of my biggest lessons from building this project:
Good security isn't always about finding one unbreakable wall. Sometimes it's about building several walls that make the wrong path increasingly difficult.
What I'd Improve Next
Device binding solved another problem, but it also opened up several areas I'd like to improve:
- Better device-recovery workflows
- More explicit trusted-device management
- Suspicious device-change logging
- Better administrator controls
- More robust handling of device identity resets
These are the kinds of problems that only become visible after the basic system actually exists.
Final Thoughts
I started with:
"How do I stop someone from sharing a QR code?"
Then:
"What stops them from sharing an account?"
And finally:
"How do I know this request is coming from a trusted device?"
That progression is what changed this project for me.
I didn't design the final architecture in one sitting.
The architecture evolved as every solution exposed another problem.
And that's probably much closer to how real software gets built.
🔗 Project
GitHub:
https://github.com/siddarthpatelkama/UBA-veltech-attendance-system
LinkedIn:
https://www.linkedin.com/in/siddarthpatelkama
If you're building an authentication system of your own, I'd be curious to know: would you use device binding, or would you solve this problem differently?