S
Home Application Security ยท Updated 2026-07-14

Magic Links

A magic link is a URL, delivered by email or SMS, that authenticates a user or authorises an action the moment it is clicked โ€” no password required. They are convenient, which is exactly why they have become a preferred phishing vector: an attacker who can make a user click any link can just as easily make them click a malicious one, and the user has been trained by every magic-link flow they've ever used that clicking an emailed link to log in is normal, expected behaviour. As a general rule, email-delivered authentication links should not be used as a login mechanism. This article covers why, and how to handle the cases where a link-based flow is genuinely difficult to avoid.


The core problem is behavioural, not cryptographic. Every legitimate magic-link email reinforces the exact action a phishing email needs the victim to take: click this link to sign in. A well-executed phishing email that mimics the organisation's magic-link template is indistinguishable from the real thing to most users, because the real flow is itself "click a link from your inbox to get authenticated." Security awareness training that says "never click login links in email" is directly undermined by a product that routinely sends login links by email.

Email Is Not an Authentication Factor

A magic link is only as strong as the mailbox it is delivered to. Email accounts are frequently protected by weak or no MFA, are a common target for credential stuffing and OAuth consent phishing, and are often accessible from shared or unmanaged devices. Treating "possession of the email inbox" as equivalent to "possession of a security key" conflates a weak, frequently-compromised channel with a genuine authentication factor.

No Origin Binding โ€” Vulnerable to Real-Time Relay

Unlike FIDO2/WebAuthn (see Multi-Factor Authentication), a magic link is a bearer token: whoever has the URL, from whatever origin, is authenticated. An adversary-in-the-middle phishing kit can present a cloned login page, capture the email address, and โ€” if the attacker also has read access to the mailbox (a prior email compromise, a shared support inbox, a forwarding rule planted after an earlier breach) โ€” complete the flow without the victim ever suspecting anything.

Magic links routinely leak through channels the sender does not control:

  • Corporate email security gateways and link scanners (Proofpoint, Mimecast, Microsoft Defender for Office 365 Safe Links) pre-fetch links to check for malware. A single-use magic link can be consumed by the scanner before the user ever clicks it, breaking the flow or โ€” worse โ€” a link that is not single-use gets silently authenticated by the scanner's crawler.
  • Referrer headers can leak the full link (including the token) to third-party resources if the destination page loads external assets before validating the token.
  • Browser history, shared mailboxes, mailing list archives, and forwarded emails can all expose a still-valid link to someone other than the intended recipient.
  • Server and proxy access logs capture the full URL, including the token, if it is placed in the query string.

Long-Lived, Replayable Tokens

Because magic links are designed for asynchronous delivery (the user may not check their inbox for minutes or hours), the tokens are often given a longer validity window than a typical session or OTP. A longer-lived, unrevoked bearer token sitting in an inbox is a standing credential โ€” exactly the kind of "collect now, use later" target that makes mailbox compromise valuable to an attacker.


Do not use email-delivered links as a primary login or step-up authentication mechanism. Use phishing-resistant MFA (FIDO2/WebAuthn, passkeys) or, at minimum, a code the user must manually type into the application they are already on โ€” see the ranked factor guidance in Multi-Factor Authentication. A code that must be typed back into the original tab preserves origin binding in a way a clickable link does not: the user is proving they received something, on the site they explicitly navigated to, rather than being taken wherever the link points.

This prohibition should be a default in application design reviews and threat models: any proposal to email a clickable authentication link should be treated the same as a proposal to email a password, and should require an explicit, documented exception.


Legitimate Exceptions

Some flows are genuinely difficult to solve without an email link, because the entire premise of the flow is that the user does not yet have a working credential to authenticate with by any other means. These are the accepted exceptions โ€” not because the risk disappears, but because the alternative (no verification path at all, or a weaker one) is worse.

Use Case Why a Link Is Hard to Avoid
User enrolment / initial account activation The user has no password, no registered MFA factor, and often no prior relationship with the system. Email is the only channel already proven to reach them (their invite, their corporate address).
Password reset By definition the user cannot authenticate with the credential they are trying to recover. A secondary channel is required to re-establish trust before a new credential can be set.
Email address verification The explicit purpose of the flow is to prove control of the mailbox โ€” a link sent to that mailbox is the mechanism, not a workaround.
B2B/B2C invitations (e.g. inviting an external user into a shared workspace) The invitee has no account and no established authenticator; email is the identifier being invited.

Even within these exceptions, the goal is to minimise and contain the risk rather than treat the link as a safe default. The controls below apply specifically to these accepted use cases.


Token Construction

Requirement Detail
Entropy Minimum 128 bits, generated with a CSPRNG โ€” never a sequential ID, timestamp, or predictable value
Single use Token is invalidated immediately on first successful use, regardless of outcome
Short expiry 15 minutes for password reset/enrolment; as short as operationally possible
Storage Store only a hash of the token (SHA-256), never the raw value โ€” same principle as password storage
Placement Path segment or fragment, not a query parameter that gets logged by default in most web server configurations
import secrets
import hashlib

def generate_reset_token() -> tuple[str, str]:
    token = secrets.token_urlsafe(32)          # sent to the user, never stored
    token_hash = hashlib.sha256(token.encode()).hexdigest()  # stored server-side
    return token, token_hash

Email security gateways and client link-preview features will fetch a URL to inspect it before the user clicks. A naive single-use token gets burned by the scanner, not the user.

  • Require an interstitial confirmation page for the first GET on the link โ€” display a "Click to continue" button that performs the actual state-changing action via POST. Scanners that only fetch the link do not trigger the follow-on action.
  • Do not perform the sensitive action (password reset, session creation) on the initial page load. Treat the link GET as "this token exists and is valid," and require an explicit user action afterward.
  • Bind the token to the request context where possible: the IP range or device that initiated the reset/enrolment request, checked (not strictly enforced, to avoid breaking legitimate cross-device flows) against the IP/device that redeems it, with a step-up challenge on mismatch.
  • Bind the token to the specific account/email address it was issued for โ€” never accept a valid token for a different identifier than the one embedded server-side.
  • Re-authenticate for anything beyond the minimum purpose. A password-reset link should let the user set a new password and nothing else โ€” it must not become a general-purpose login session with full account access.

Session and Scope Limits

  • The session established by consuming a magic link should be scoped to the single purpose (e.g. "set new password") and should expire immediately after that action completes.
  • Do not treat a redeemed magic link as equivalent to a fully authenticated, long-lived session with access to sensitive account settings (payment methods, MFA enrolment changes) without an additional step-up check.
  • Log every issuance and redemption event (timestamp, requesting IP, redeeming IP, outcome) โ€” feed to the same monitoring pipeline as failed login and MFA events.

Notify and Give an Escape Hatch

  • Notify the user through a second channel (existing verified email, push notification to an already-enrolled device) whenever a reset or enrolment link is issued, so an attacker-initiated request is visible to the legitimate owner.
  • Rate-limit link issuance per account and per IP to prevent an attacker from flooding a victim's inbox with reset requests as a precursor to social engineering ("just click the last link I sent you").

What Not to Do

  • Do not use magic links for routine, repeated sign-in ("passwordless login" as a everyday convenience feature) โ€” this is the exact pattern that normalises clicking authentication links from email and is the highest-risk form of this pattern.
  • Do not make the token long-lived "for user convenience" โ€” every extra hour of validity is an extra hour the token is a standing credential sitting in an inbox.
  • Do not skip the interstitial confirmation step to "streamline the flow" โ€” this is the single most common way single-use tokens get silently burned by security scanners, and removing it also removes the last barrier between a pre-fetch and a completed account takeover.
  • Do not reuse the same token generation/validation code path for high-privilege actions (e.g. changing a registered MFA factor, adding a payment method) as for low-privilege ones (e.g. verifying a newsletter subscription).

Hardening Checklist

Control Priority Notes
Email links prohibited as a routine/repeated login mechanism Critical Use phishing-resistant MFA instead โ€” see Multi-Factor Authentication
Magic links restricted to enrolment, password reset, and email verification flows Critical Documented, explicit exceptions only
Tokens generated with a CSPRNG, โ‰ฅ128 bits entropy Critical Never sequential, timestamp-based, or predictable
Tokens single-use and invalidated immediately on redemption Critical Prevents replay from scanners or leaked copies
Token expiry โ‰ค 15 minutes High Shorter where operationally feasible
Only a hash of the token stored server-side High Same principle as password storage
Token not placed in a logged query parameter Medium Avoid leakage via server/proxy access logs
Interstitial confirmation step before the sensitive action executes Critical Prevents email security scanners from consuming single-use tokens
Redeemed session scoped to the single purpose, expires immediately after High Not a general-purpose authenticated session
Second-channel notification on link issuance High Surfaces attacker-initiated requests to the legitimate owner
Link issuance rate-limited per account and per IP High Prevents inbox flooding / reset-request social engineering
Issuance and redemption events logged and monitored High Same pipeline as failed login / MFA events

References

The Security Architecture Site โ€” for internal reference use. Back to contents