June 3, 2026
When “One-Time” Isn’t Enough: The Case of the Reusable Magic Link
Introduction
Just_try_shit
3 min read
When "One-Time" Isn't Enough: The Case of the Reusable Magic Link
Introduction
The shift toward passwordless authentication is one of the most positive trends in modern security. Magic links, in particular, offer a seamless user experience by eliminating the friction of remembering and typing passwords. For security teams, however, they introduce a new critical requirement: bulletproof token lifecycle management.
While testing a web application through its bug bounty program, I came across an interesting case study in this area. I discovered that their magic links could be reused multiple times after a successful authentication. Although the report was ultimately a duplicate, it provides a perfect lesson on a subtle but critical security pitfall.
Magic Links: A Temporary Password in Disguise
Functionally, a magic link is a one-time password delivered via email. Instead of a user supplying a secret, the link itself becomes the credential. This mechanism shifts a critical security burden from the user to the backend.
For a magic link to be secure, two rules must be enforced absolutely:
-
Time-bound validity: The token must expire after a short, predefined window.
-
Single-use enforcement: The token must be irrevocably invalidated immediately after the first successful authentication.
3.Failing on either point transforms a secure, one-time credential into a persistent, reusable one — which is precisely what I found.
The Discovery
My test began with a routine review of the authentication workflow. I requested a magic login link and received the standard email, which explicitly stated:
"This link and code will only be valid for the next 5 minutes."
This phrasing set a clear expectation for time-based expiry. But what about single use? I logged in with the link in my primary browser. The authentication was successful. Then, I copied the exact same URL and opened it in a second, completely different browser.
Reproducing the Flaw
The issue was trivial to reproduce:
-
Request a magic login link from the application.
-
Authenticate successfully using the link in Browser 1.
-
Copy the exact URL from Browser 1's address bar.
-
Open that copied URL in Browser 2. A new authenticated session is created.
-
Reuse the same URL in Browser 3. Yet another session is granted.
Observed vs. Expected Behavior
Observed: The application created multiple independent, authenticated sessions from a single magic link. The token remained viable for its entire 5-minute lifespan, regardless of how many times it was used.
Expected: A secure implementation would treat the token like a piece of paper that says "BURN AFTER READING." After the first successful use, the backend should mark the token as consumed. Any subsequent request with that token should be rejected with a clear error, such as "Link already used" or "Token invalid."
The Real-World Security Impact
The obvious counterargument is that an attacker would need access to the magic link in the first place. While true, this overlooks common real-world scenarios where a reusable token significantly amplifies risk:
- Email Forwarding: Users often forward emails between personal and work accounts. A reusable token in a forwarded message is a persistent credential accessible to anyone in the forwarding chain.
- Browser History & Session Theft: Magic links are long, unique URLs that often sit plainly in a browser's history. If an attacker gains access to browser history files or session logs, a reusable token remains a valid key.
- Logging and Proxy Systems: URLs can be inadvertently captured by server logs, corporate web proxies, and browser extensions. A single-use token would be worthless if captured post-use; a reusable one is a golden ticket.
- Shared Device Scenarios: On a shared or family device, even a brief moment of unattended access is enough to click a history link that should have been dead.
The root cause was clear: missing token invalidation. The application enforced the time constraint but completely missed the one-time constraint, effectively downgrading a single-use token into a multi-use credential.
The Fix: Proper Token Lifecycle Management
A secure magic link implementation is a state machine with three states for any token: Active, Consumed, and Expired. The fix involves a strict database transaction when a link is used:
-
Atomic Check and Invalidate: In a single transaction, check if the token's status is
Activeand within its time window. -
Consume the Token: If valid, immediately update the token's status to
Consumedand then create the user's session. -
Reject All Others: Any concurrent or subsequent request will find the token in a
ConsumedorExpiredstate and must be immediately rejected. -
Supporting Controls: Maintain a short expiration window (e.g., 5 minutes) and notify the user of any new session creation on their account.
Disclosure and Outcome
I submitted the finding through the application's bug bounty program, categorizing it as "Weak Password Reset Implementation — Token Is Not Invalidated After Use." The submission was quickly closed as a duplicate of a prior report. While finding a duplicate is always a bit of a letdown, it validates that other researchers are paying attention and that the security community is collectively raising the bar.
Final Thoughts
Passwordless authentication offers a fantastic user experience, but it must be built on a foundation of zero-trust principles. A magic link is not just a "link"; it is a bearer token that grants full account access. It must be treated with the same security rigor as a one-time password.
The difference between a secure system and a vulnerable one often comes down to these small, backend implementation details. If the token lifecycle isn't airtight, you haven't eliminated the password; you've just changed its shape and accidentally made it reusable.