Email login
Set up email and password login and magic links. Default login screens are included.
Your app has login and sign-up screens as soon as your worker calls env.auth. You do not have to build them yourself.
| Path | Screen |
|---|---|
/__runlot/auth/sign-in | Login |
/__runlot/auth/sign-up | Sign-up |
/__runlot/auth/forgot | Forgot password |
/__runlot/auth/reset | Reset password |
/__runlot/auth/signed-out | Signed out |
Your worker only receives requests that do not start with /__runlot/auth, and it handles those requests exactly as before.
Using your own login screens
To use your own forms instead of the default screens, post to these paths.
await fetch("/__runlot/auth/sign-up/password", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ email, password }),
});
await fetch("/__runlot/auth/sign-in/password", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ email, password }),
});POST requests sent from a browser must carry an Origin header (or a Referer if there is no Origin) pointing at the same host. If neither header is present, the request is rejected.
Magic links
Instead of a password, send a login link by email.
await fetch("/__runlot/auth/sign-in/email", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ email }),
});When the user opens the link they receive, a session is created immediately.
An email with no account gets a link too while sign-up is open. Opening it creates the account with the email already verified. With sign-up closed, nothing is sent to an unknown email. The answer is the same either way, so the request does not reveal whether an account exists.
Password rules
- At least 8 bytes, at most 256 bytes
- Hashed with argon2id (19 MiB of memory, 2 iterations)
- Plaintext passwords are never stored
Login attempt limits
After 10 failed logins in 15 minutes from the same email address, or 30 failed logins in 15 minutes from the same IP address, requests are blocked for a while. The counters live in node memory, so they reset when the process restarts.
Settings
runlot auth set allow-signup off # Disable new sign-ups (default: on)
runlot auth set require-verified on # Block login until the email is verified (default: off)
runlot auth set session-days 7 # Session lifetime (default: 30 days)
runlot auth set brand-name "My App"
runlot auth set brand-color "#0f6f8f"
runlot auth set brand-logo https://example.com/logo.svgThe branding settings are applied to the default login screens.
How email is sent
In the default development environment, login links are written to the project logs instead of being emailed. You can read them with runlot logs. For how mail is actually sent, see Sending email.