Development · 0.2.0.dev

Sign in with an email link

Reviewed 2026-09-07

Let an existing account sign in using a link delivered by your Rails app.

Enable email-link sign-in

After the quickstart prerequisites, run:

Shell
bin/rails generate latchkey:email_link
bin/rails db:migrate
bin/rails latchkey:doctor

This also adopts hardened sessions. Configure base_url, mail_from, mail delivery, a queue and a rate-limit cache. The deployment checklist separates a local trial from a durable setup.

What the user does

  1. Open /sign-in and request a link for an existing account.
  2. Check their email and open the link.
  3. Submit the confirmation form to finish signing in.

Opening the link alone does not consume it. Confirmation requires a POST, so email scanners and link previews do not sign the user in merely by fetching the URL. Links expire after 20 minutes by default and may be used once.

The request page uses a generic response for unknown, ineligible and throttled accounts. A success-looking request screen is not proof that a message was sent.

This diagram shows a successful confirmation. An expired, replaced or already-used link is rejected instead of creating a session.

Resend and expiry

Request a new link when one has expired or already been used. Use the newest message. Issuing a replacement invalidates the prior link, and resend requests are rate-limited.

Password and email-address changes made through the host’s Rails lifecycle invalidate outstanding links, including while email sign-in is temporarily disabled. Direct database updates bypass those lifecycle callbacks.

Choose browser binding

Cross-device sign-in is allowed by default. To require the browser that requested the link, set:

Rubyconfig/initializers/latchkey.rb
config.email_link.same_browser = true

A link opened elsewhere will be rejected. Test this with your actual mail client: in-app browsers and a device’s default browser can have different cookies.

Verify and troubleshoot

Follow a delivered link and confirm the new session under /sessions. Try the same link again; it should be rejected. With browser binding enabled, test a second browser too.

For no email, an old link or the wrong-browser state, use troubleshooting. Keep raw links and local mail files out of logs, screenshots and public support requests.

Something unclear? Suggest a correction Development source status

Search documentation

Type to find a guide.

Use Tab to move through results. Escape closes search.