Magic-link auth: the decisions the gem does not make for you
A Rails 8 starting template with the authentication decisions already made rather than left to the gem.
Sorcery for passwordless magic-link login plus Google OmniAuth, on PostgreSQL with Tailwind and Resend. The README still describes Zenstream, which occupied this repo before it became a template.
A gem gives you primitives; the decisions are yours. A magic-link token needs a lifetime short enough that an old email in an inbox is not a standing key, and single-use consumption so a forwarded link cannot be replayed. Activation and authentication have to be separate states, or an unactivated account is signable-into by anyone who finds the flow. The one people skip is account linking: when the same address arrives once by magic link and once via Google, you either link silently, which trusts Google’s email verification, or keep them separate, which is safer and leaves a user with two accounts and no idea why. There is no clean answer, and the point is to pick deliberately rather than find out later which you picked.
Brute-force protection, session timeout, remember-me, and signup and last-login IP capture round it out. Session timeout and remember-me pull against each other, and that interaction fails silently in the wrong direction.