Magic link (passwordless)
POST .../request-magic-link ({ email, redirectUrl? }) emails a
single-use sign-in link instead of a password or a typed-back code.
Disabled by default — enable it per collection with
authOptions.magicLink.enabled (see Settings
and collection options). Like
request-otp, it always answers 200, even for an unknown address,
so it can’t be used to enumerate accounts.
The token is a random 48-character string, hashed (SHA-256, same
trade-off as an OTP code) into a new _magicLinks row alongside a short
TTL (authOptions.magicLink.duration, default 900 seconds). The emailed
link is either authOptions.magicLink.urlTemplate (default
{APP_URL}/auth/magic-link?token={TOKEN}) or a caller-supplied
redirectUrl, but only when it’s same-origin as settings.meta.appURL
— anything else falls back to the template, so a request body can’t be
used to redirect a login link off-site.
POST .../auth-with-magic-link ({ token, mfaId? }) looks the token up
by its hash, consumes it either way (a correct token or an expired
one), and goes through the same ban/MFA
gate and new-location login alert
as every other login. A successful magic-link login marks the record
verified, exactly like a successful OTP
login does — clicking the link proves control of the mailbox just as well.
See Email → Recipes for a minimal React
sign-in-page example using @cratebase/react’s useMagicLinkCallback.