Magic Link & Email OTP
Two ways to sign a user in without a password, both of which prove control of an inbox: a link they click, or a code they type. Neither stores a password, so neither has a password to leak or reset.
They are enabled through different mechanisms — the link is a strategy entry, the code is not. That asymmetry is the one thing to get right on this page.
Magic Link
A strategy entry. The user submits their email, receives a one-time link, and is signed in by following it.
auth:
strategies:
- type: magicLink
expirationMinutes: 30
| Property | Description |
|---|---|
expirationMinutes |
Link lifetime in minutes (positive integer). Defaults to 15. |
The default 15 minutes assumes the user is waiting on the mail. Stretch it when your audience checks email on a phone, later; shorten it when the link grants access to something sensitive, since a live link in an inbox is a live credential.
The message body is rendered from the magicLink email template when you supply one, with $url substituted for the link.
Enabling Email-OTP
Email-OTP delivers a numeric one-time code instead of a link — better on a device where following a link would break the flow, and easier to read aloud over a phone.
There is no type: emailOtp strategy entry. The flow activates when you define the emailOtp email template; its presence is what mounts the plugin.
auth:
strategies:
- type: emailAndPassword
emailTemplates:
emailOtp:
subject: Your sign-in code
text: 'Your verification code is $code. It expires shortly.'
$code is substituted with the generated one-time code. Note the strategy array above declares only emailAndPassword — email-OTP rides alongside whatever strategies you declared, it does not replace them.
Adding type: emailOtp to strategies is a validation error. The union accepts emailAndPassword, magicLink and oauth only, so a config that guesses at an OTP strategy fails sovrium validate rather than booting without the flow.
Both Need SMTP
A passwordless flow that cannot send mail cannot sign anyone in. When SMTP is unset the app boots with email disabled and logs a warning — sign-in attempts then fail silently, with the user waiting on a message that was never sent.
Configure SMTP before shipping either flow, and prefer keeping emailAndPassword declared alongside them while you do: it gives you a working way in if mail delivery breaks. See Environment Variables for the SMTP settings.
Related Pages
- Strategies Overview — the
strategiesarray and how to choose. - Email Templates — the
magicLinkandemailOtpbodies and their variables. - Email & Password — the credential strategy these sit beside.
- Environment Variables — SMTP configuration and
BASE_URL. - Sessions — the session a successful link or code issues.
Last updated July 27, 2026
This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta — contributions and corrections are welcome.