Back to Explore
GuideVibeFix 编辑部Updated Oct 31, 2026

Login Without Remembering a Password: Magic Link and Email Codes for Vibe Projects

Magic Link is the best-value passwordless option for a solo team, but login security then depends on mailbox security and email deliverability. This guide covers seven link-security rules, delivery testing, cross-device handling, and fallbacks.

A man drinking coffee while checking his phone for a login email
A man drinking coffee while checking his phone for a login email

__MEDIA_1__

Bottom line first: for a solo team with a small product, Magic Link (email login links) is the best-value passwordless option. It removes a whole chain of password problems — forgotten passwords, weak passwords, credential stuffing — and it is far cheaper and easier to integrate than Passkeys or SMS codes. But it has one hard limitation you must accept up front: your login security now depends on the security of the user's mailbox, and on whether your emails actually arrive on time. This guide is about getting both of those things right.

The example product "Green Sprout List" and its founder "Shen Qing" in this article are fictional, used only to explain the flows. They do not correspond to any real product.

Boundaries: what this guide does not cover

Several neighbouring guides on this site already cover adjacent topics, each with a different job: the Passkey guide covers device-biometric login, for the "this device is me" case; the SMS code guide covers phone-number login, which is billed per message and involves SMS gateway providers; the login-and-permissions guide covers the overall account system and role design. This guide covers exactly one thing: proving "you are you" with email — Magic Link and email verification codes, plus the deliverability, security, and fallback problems they share. If you already decided on password login and just want a "forgot password" feature, that is not this guide's scenario; see the password-reset section of the login-and-permissions guide.

Two forms: pick one primary form

Magic Link and email codes are the same credential in two carriers: one is a link you click to log in, the other is a 6-digit number you type in. Do not ship both and let users choose — that doubles your testing load and your support questions. Choose based on a single question: what device do users mainly log in on?

If users are mostly in a mobile app, or frequently switch between computer and phone, prefer Magic Link. One tap and they are in, with no numbers to copy between devices. But watch for a classic trap: the user requests a link on a computer, then opens it from the phone's mailbox — and the link logs them in on the phone's browser, not on the computer. The fix is in the "cross-device" section below.

If users mainly operate on a single device, or if many of your users have corporate mailboxes that rewrite links into security redirects (which can burn a link before the user ever clicks it), prefer a 6-digit code. Numbers can be read out loud and copied, and they have the best compatibility. The cost is one extra input step, plus brute-force protection you have to build yourself.

Green Sprout List (fictional) shipped both at first, and half of its support tickets became "I clicked the link and also typed the code — which one counts?" Later it kept Magic Link as the primary path and codes only as a fallback: the "use a code instead" entry appears only when a link fails to open. The main path is always exactly one.

Seven security rules for links: do not ship missing any of them

Magic Link security does not rest on "the link is long so nobody can guess it." It rests on a set of rules that back each other up. The seven below are hard pre-launch checks; AI-generated code most often drops the later ones, so check them one by one:

  • Store only the token's hash, never the plaintext. If your database leaks, plaintext tokens are a master key to every account. Generate 32 random bytes, store the SHA-256 hash, and put the original value only in the email. When verifying, hash first, then compare.
  • 15-minute expiry. Do not copy products that give 24 hours. The longer a link sits in a mailbox, the more likely it is to be forwarded, archived, or found by someone else. Fifteen minutes is plenty for a normal user; after that, send a new one.
  • Single use; void it the moment it is used. Whether login succeeds or a retry fails, a second use of the same token must be rejected. Otherwise a user who forwards the email to a colleague "to take a look" has also handed them a login.
  • A new link voids all older links. If a user clicks "resend" three times, three links sit in the mailbox and only the last one may work. Otherwise the user clicks the first, stale link, fails to log in, and assumes your product is broken.
  • Never reveal whether an account exists. For an unregistered email, show exactly the same message as for a registered one — "if this email is registered, a login link has been sent" — with identical wording and timing. Otherwise your login box becomes a user-enumeration tool: an attacker can probe email after email to learn who your users are.
  • Links must use HTTPS on your own domain. Do not use your email provider's default redirect domain as the login domain. Users hesitate at an unfamiliar domain, and phishers can imitate exactly that pattern. The link domain must match your product's main domain.
  • Send a notification on every successful login. A "your account just signed in on a new device" email or in-app notice is the last line of defence. If the real user did not sign in but gets the notice, they can immediately change their email password and ask you to freeze the account.

The code form follows mostly the same rules, plus two more: a 6-digit code has only one million combinations, so you must cap attempts (for example, lock the email for 15 minutes after 5 wrong tries) and cap sending frequency (at most once per minute and 5 times per hour per email). Otherwise an attacker can script slow guesses, or abuse your sending endpoint to spam someone else's mailbox.

Email deliverability: a login link is first of all an email that must arrive

Many Magic Link launches fail on day one not because the code is wrong, but because the email lands in spam or is rejected outright. Treat login-email deliverability as part of the login feature, not as something to fix after users complain.

Step one is getting sender identity right: send from your own product domain (a dedicated login subdomain works well) and set up SPF, DKIM, and DMARC DNS records. Those three tell the receiver "this email really came from me and was not tampered with." AI-generated code often stops at wiring up the sending API, with nobody configuring the DNS records — and then Gmail flags the mail as suspicious.

Step two is testing real behaviour across mainstream mailboxes. Register test accounts on Gmail, Outlook, QQ Mail, and 163 Mail at minimum, and run the full flow — request link, receive mail, click link — recording how long each mailbox takes from send to delivery. If one mailbox consistently takes over a minute, your "15-minute expiry" is effectively "14 minutes" for its users, and your copy should say "the link is valid for 15 minutes; if it hasn't arrived, check your spam folder" rather than a bare "email sent."

Step three is handling links that get clicked before the user sees them. Corporate mailboxes and some security gateways "pre-visit" links on arrival to scan them, which burns your single-use link in advance. Two mitigations help: first, make the link land on a "confirm sign-in" page, and only consume the token when the button is clicked; second, when a link is found already consumed but no session was created, show a precise message — "this link has already been used, please request a new one" — not a vague "login failed." Green Sprout List (fictional) was bitten by this three times in its first week; after switching to "click the link, then confirm, then sign in," the related support tickets went to zero.

Pages and copy: turn waiting into something predictable

Half of Magic Link's user experience lives in page copy. After clicking "send link," users anxiously ask three questions: which mailbox did it go to? How long do I wait? What if nothing arrives? Your page must answer all three before users have to ask.

The "link sent" page should state four things: the destination mailbox (partially masked in the middle is fine), the link's validity period, a reminder to check the spam folder, and a "resend" button with a cooldown countdown (60 seconds). Not just a lonely "email sent."

Handle the cross-device case explicitly: if the user requested the link on a computer but opens it on a phone, the phone signs in, but the computer page must not spin forever. The fix: the computer page polls login status (asking the server every 3 seconds whether this request has completed), and signs in automatically once the phone completes it; if nothing completes within 5 minutes, the computer page suggests "still nothing? Resend, or switch to a code."

Expiry and invalid pages need plain language too. Never show an internal error code like "token_invalid." Three cases, three messages: "this link has expired, please request a new one," "this link has already been used — each link works only once," and "this link is invalid — please make sure you opened the latest email." When users can solve it from the message alone, they never reach support.

Fallback: what happens when the mailbox itself is unavailable

Even the best Magic Link flow meets users who cannot receive mail: their provider is down, they changed mailboxes, their company mailbox was deactivated. A login system with no fallback hands the power to recover an account entirely to the email provider.

The minimum viable fallback has two parts: first, keep an alternative login method — usually a password or OAuth (Google/GitHub sign-in) — so users can still get in when email fails; second, write down the manual verification standard for support — what the user must provide (registration date, recent order, last four digits of a bound phone number) before support may manually change the bound email, instead of a verbal "I'll change it for you."

Think in the other direction too: the fallback must not become a back door. If passwords are the fallback, password security requirements (length, lockout on errors, breach detection) must not be relaxed at all — otherwise attackers will ignore Magic Link entirely and walk through the weakest channel. A security chain is only as strong as its weakest link.

Launch checklist

Check every item before launch: tokens stored as hashes with 15-minute expiry, single use, new links voiding old ones, no account-existence leakage, link domain matching the product domain, login-success notifications, attempt and frequency limits for codes, real end-to-end tests on Gmail, Outlook, QQ Mail, and 163 Mail, a confirmation page covering corporate pre-visit scanning, a sent page stating the mailbox, validity period, and resend cooldown, distinct copy for expired versus already-used links, and a documented fallback login method plus support email-change procedure. Any missing item will come back as support tickets after launch.

One last blunt truth: Magic Link is not "remove passwords and you are secure." It moves password hassles onto the mailbox and the mail system. If you spend half a day getting DNS, expiry policy, and failure copy right, it is the lowest-effort login option a solo team can run; if you just let an AI generate a send-a-link endpoint and ship it, it is the login option most likely to blow up on day one.

Six sentences to put in your prompt when AI generates the code

Solo teams usually have AI write the login code. The code generally runs; the problem is that requirements never mentioned in the prompt get implemented the laziest way. Copy these six sentences into your prompt and the output gets much more reliable: first, tokens use cryptographically secure random numbers and the database stores only hashes; second, tokens expire in 15 minutes, are single-use, and a newly issued token voids older ones; third, registered and unregistered emails return identical copy and response timing; fourth, login-link domains must match the product's main domain over HTTPS; fifth, a new-device notification goes out on every successful login; sixth, every failure case (expired, already used, invalid) returns a distinct business error code so the frontend can show distinct Chinese copy, and error codes are never passed through to users raw.

When you receive AI-generated code, do not just check "can I log in." Run through this review list: does the token table have an expiry field and a used flag? Is the verification order "check hash, then expiry, then used flag, then mark used"? Get the order wrong and you get odd bugs like "an expired link was marked used, so the user's reissued link is judged a duplicate." Does the resend endpoint have rate limits? Is the session regenerated on login, with old sessions invalidated? Is the link in the email template a full URL rather than a relative path? If any of these five cannot be answered, do not merge the code yet.

The first week after launch: watch four numbers

Launch is not completion. Four numbers in the first week will tell you what is still wrong: first, the median time from clicking send to the user opening the link — normally under 1 minute; over 3 minutes means checking the sending channel and receiver delays; second, the link-expiry rate, the share of issued links that end up expiring — over 10% means your validity copy or delivery speed has a problem, so check the spam rate first, then consider widening expiry from 15 to 30 minutes, rather than jumping straight to several hours; third, the resend rate — a single user resending more than 3 times in a day usually means corporate-gateway pre-visits burning links or mail delays, handled by the confirmation-page fix above; fourth, the share of support tickets about "mail never arrived" — if they appear three days running, do not just reply "please check spam"; check whether SPF, DKIM, and DMARC on the sending domain are genuinely live and whether some provider is rejecting you outright.

One easily missed metric: the volume of "change bound email" requests within 24 hours of a successful login. A sudden rise may mean someone is bulk-testing links against leaked mailboxes — single-use links are hard to guess, but attackers can still use your sending endpoint to spam many users. Tighten per-email sending frequency another notch, and state clearly on the sent page: "if you did not request a sign-in, ignore this email," so recipients of harassment mail feel reassured rather than panicked.

FAQ: the five questions you will definitely be asked before launch

"What if a user has no email?" — Then they are not Magic Link's target user. Keep a password or OAuth channel for them, but do not complicate the main path for a minority. The main path serves 95% of people; the fallback serves the remaining 5%.

"Can a link stay valid long-term so users can bookmark it?" — No. A long-lived login link is a key with no expiry: once the mailbox leaks or an old email is dug up, the account goes with it. What users want is "every login is convenient," not "bookmark one link forever." The former is delivered by "remember this device for 30 days"; the latter is a security hole.

"How do you do 'remember this device' safely?" — On successful login, issue the device a long-lived refresh credential (an HttpOnly, Secure, SameSite cookie) valid for 30 days, with a device list page where each device can be revoked individually. What is remembered is the device, not the email link; the link itself stays single-use.

"Can codes and links share one token system?" — They can share a storage table, but not a verification entry point. A link token is 32 random bytes and a code is 6 digits; their attempt limits, expiry policies, and error copy all differ. Sharing the table is fine; sharing verification logic will skew one side's limits.

"How do you test in a test environment?" — Give the test environment its own sending domain or sandbox sending channel, and never send test links to real user mailboxes; also set up a test-mail inbox service for test accounts so test mail content can be read directly. The worst habit is sending repeated test links to your own real mailbox in production for convenience — that pollutes production data and may trigger rate limits that hurt real users.

Views 0Comments 0

Comments (0)

ME
0/1000
Loading comments...
Browse projectsPublish your project

Related articles

A real photo of a person writing notes in a notebook beside a laptop at a desk, echoing the theme of leaving notes for your future self
Guide
Pick It Up After Three Months: A Continuity Handbook for Solo Projects

Solo projects rarely die because they cannot be built. They die because, once put down, they cannot be picked up again. This guide covers the five-part continuity handbook, how to write for a forgetful future self, resuming AI-assisted work, and the day-one restart order.

Developer WorkflowIndie DevelopmentLearning & Career