pushery / email-magic-link-for-laravel
Passwordless email magic-link & OTP authentication for Laravel — standalone or with a correct, no-bypass Fortify 2FA handoff and scanner-safe link consumption.
Package info
github.com/pushery/email-magic-link-for-laravel
pkg:composer/pushery/email-magic-link-for-laravel
Requires
- php: ^8.4
- ext-json: *
- laravel/framework: ^13.0
Requires (Dev)
- cweagans/composer-patches: ^1.7
- larastan/larastan: ^3.0
- laravel/fortify: ^1.0
- laravel/pao: ^1.1
- laravel/pint: ^1.0
- orchestra/testbench: ^11.0
- pestphp/pest: ^5.0
- pestphp/pest-plugin-agent: ^5.0
- pestphp/pest-plugin-browser: ^5.0
- pestphp/pest-plugin-evals: ^5.0
- pestphp/pest-plugin-laravel: ^5.0
- pestphp/pest-plugin-phpstan: ^5.0
- pestphp/pest-plugin-rector: ^5.0
- pestphp/pest-plugin-type-coverage: ^5.0
- pushery/wirekit: ^2.26
- rector/rector: ^2.0
- spaze/phpstan-disallowed-calls: ^4.12
Suggests
- laravel/fortify: Enables the no-bypass two-factor (TOTP) handoff: a magic-link user with confirmed 2FA completes Fortify's challenge before being logged in (^1.0).
- pushery/wirekit: Renders the sign-in screens with WireKit components when installed; the package auto-detects it and falls back to plain Blade otherwise. The screens are developed and tested against 2.26 and up: the one-time-code field needs the alphabet prop (2.22) to accept a non-numeric code at all, and its case-folding validation pattern (2.26) to accept that code in lower case without scripting.
This package is auto-updated.
Last update: 2026-08-05 07:39:36 UTC
README
Email Magic Link for Laravel
Passwordless email authentication for Laravel — magic links and one-time codes — that works standalone or alongside Laravel Fortify.
Plenty of packages send a magic link. This one is built around two properties most of them get wrong:
- A correct, no-bypass Fortify two-factor handoff. A user with confirmed TOTP is handed to Fortify's own challenge in a not-yet-authenticated state; the login completes inside Fortify only after the code is verified. There is no path that signs a two-factor user in without the second factor.
- Scanner-safe and prefetch-safe link consumption. The emailed link is a signed, inert
GETthat only renders a confirmation page. The single-use token is spent solely by an explicitPOST, so SafeLinks, Mimecast, Proofpoint and browser prefetch cannot burn the link before the human clicks "Sign in".
Installation
composer require pushery/email-magic-link-for-laravel
Requires PHP ^8.4 and Laravel ^13.0. Laravel Fortify (^1.0) is optional and only needed for the two-factor handoff. There are no third-party runtime dependencies.
Documentation
Full docs at docs.pushery.com/email-magic-link-for-laravel
- Installation — the installer, the migration, the publish tags, and the queue worker the emails need
- Quick start — the routes you get out of the box and the flow a user walks through
- Configuration — the three Fortify setups, token lifetimes, and the invalid-link response
- Minting links and codes yourself — deliver a credential over SMS, chat, or your own transactional email
- Security model — every threat the package is designed against and the decision that addresses it
What it does
- Magic links and one-time codes — pick either, or offer both.
- A complete browser flow out of the box — six routes, the screens, and the emails; point your "log in" link at one route name.
- A Mint API — issue a signed link or a code and get it back without sending anything, to deliver over any channel you like.
- Bounded multi-use links — hand out a link redeemable N times, with the counter decremented in the same conditional
UPDATEthat consumes it, so concurrent redemptions can never exceed the limit. - Passphrase-gated links — require a shared secret, delivered out of band, before a high-value link is consumed.
- A resend guard — an escalating cooldown plus a rolling hourly cap, so a repeatedly clicked "send again" cannot flood an inbox. Reusable for your own endpoints.
- A JSON contract — stable statuses and error codes for first-party SPA and mobile clients.
- Multiple guards — sign in to an
adminguard alongsideweb, on an allowlist that keeps guards un-enumerable. - Eleven bundled locales — English, German, Spanish, French, Italian, Dutch and Portuguese, plus the
en-GB,en-US,pt-PTandpt-BRregional variants. - Styled screens, or none of ours — the sign-in views render with WireKit when it is installed, fall back to dependency-free Blade when it is not, and can be published and rewritten either way.
- Designed to fail closed — tokens hashed at rest, nothing serialized into a token, a single race-free conditional claim, and responses that never reveal whether an account exists.
Built by PUSHERY
This package is built and maintained by PUSHERY — a Berlin-based studio building Laravel applications, SaaS products, and open-source tools.
Want these sign-in screens to match a polished component library out of the box? They render automatically with WireKit, PUSHERY's open-source Livewire UI kit. Browse the rest of our work at pushery.com.
Security
Found a vulnerability? See SECURITY.md for the supported versions and how to report it.
Versioning
This package follows Semantic Versioning. It is in its 0.x line while the public API settles; the backward-compatibility promise begins at 1.0.0.
License
The MIT License. See LICENSE.