Magic Link Authentication: Passwordless Sign-In by Email
With magic links, users enter their email and click a link to sign in. No password to forget or reuse. It's popular for SaaS tools, newsletters and apps where users sign in occasionally.
The flow
- User enters their email.
- Server creates a random, single-use token, stores its hash with an expiry, and emails a link.
- User clicks the link; the server verifies the token and starts a session.
Sending the link
app.post('/auth/magic-link', rateLimit({ windowMs: 15 * 60_000, limit: 5 }), async (req, res) => {
const email = normalizeEmail(req.body.email);
const token = randomBytes(32).toString('base64url');
await db.loginTokens.create({
email,
tokenHash: sha256(token),
expiresAt: new Date(Date.now() + 15 * 60_000), // 15 minutes
browserNonce: req.signedCookies.login_nonce, // optional same-browser check
});
await mailer.send(email, 'Your sign-in link', `${SITE_URL}/auth/verify?token=${token}`);
res.json({ message: 'Check your inbox for a sign-in link.' });
});
Verifying it
app.get('/auth/verify', async (req, res) => {
const record = await db.loginTokens.consume(sha256(req.query.token)); // atomically mark used
if (!record || record.expiresAt < new Date()) return res.redirect('/login?error=expired');
const user = await db.users.findOrCreateByEmail(record.email);
req.session.regenerate(() => {
req.session.userId = user.id;
res.redirect('/dashboard');
});
});
Security considerations
- Your security is now the user's email security; offer passkeys or 2FA for sensitive accounts.
- Short expiry and single use for every link; store only token hashes.
- Email security scanners sometimes "click" links automatically. To avoid them consuming the token, show a page with a "Sign in" button that submits a POST, or pair the link with a short code.
- Consider a same-browser check (a cookie set when the link was requested) to stop a forwarded link being used elsewhere.
UX tips
- Also include a 6-digit code in the email for users who open mail on a different device.
- Use a reliable transactional email provider with SPF, DKIM and DMARC configured, so links arrive quickly and don't land in spam.
- Keep sessions long enough that users rarely need a new link.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.