A Google OAuth bug in my side project accidentally allowed citizens to access an admin dashboard.
Three months later, that same debugging experience helped me contribute to designing a secure cross-application authentication flow at work.
This post walks through the bug, how I fixed it, and how those same ideas translated into an enterprise SSO architecture.
Table of Contents
- The Side Project
- The Bug
- How I Fixed It
- The Enterprise Challenge
- Designing the Handoff Token Flow
- Security Considerations
- Lessons Learned
The Side Project
My emergency management platform, CrisisOps, has a fairly straightforward architecture.
- Node.js + Express
- PostgreSQL + Prisma
- Two frontend applications
- Citizen Portal
- Admin Dashboard
Both applications shared the same authentication backend.
Google OAuth handled authentication.
Everything worked...
Until it didn't.
The Bug
During testing, I discovered something worrying.
A citizen could:
- Sign in normally.
- Open the Admin Dashboard URL.
- Be treated as authenticated.
The backend correctly verified that the session existed.
What it never verified was whether that session belonged to the application requesting access.
Instead, the same authentication state leaked across application boundaries.
Architecture Diagram Here
The destination application exchanges that token for its own session.
The original JWT never crosses trust boundaries.
Security Considerations
Every design decision addressed a specific attack surface.
Preventing Token Leakage
Rather than storing sessions in local storage, the exchanged session is returned as an HttpOnly, Secure, SameSite=Strict cookie.
Even if an attacker successfully executes JavaScript through an XSS vulnerability, the session cookie remains inaccessible.
Preventing Replay Attacks
The handoff token is:
- Single-use
- Valid for only a few seconds
- Immediately invalidated after exchange
Even if intercepted, it becomes practically useless.
Preventing CSRF
Every transition includes a nonce (or state parameter) generated by the originating application.
The Identity Provider validates this value before issuing a handoff token, preventing unauthorized cross-site transitions.
Lessons Learned
Looking back, the OAuth bug wasn't just a bug.
It was my introduction to trust boundaries.
Three lessons stuck with me.
- Verify at application boundaries—not just user identity.
- Never pass long-lived tokens between applications.
- Side projects teach production architecture in unexpected ways.
The debugging session that once felt like an annoying weekend problem eventually became the mental model I relied on during an enterprise authentication design discussion.
Sometimes the bugs that frustrate us the most become the ideas we build systems around.
Final Thoughts
One of the biggest reasons I continue building side projects is that they let me fail in places where failure is inexpensive.
Those failures often become experience long before they're needed professionally.
Have you ever had a side project teach you something that later became useful at work?
I'd love to hear your story.
SOCIAL SHARE CARD GENERATOR