soved/laravel-magic-auth
Laravel Magic Auth adds passwordless magic link login to your Laravel app. Users sign in via a secure emailed link instead of a password, with configurable token lifetimes, single-use URLs, and simple integration into existing auth guards.
composer require soved/laravel-magic-auth, then immediately open vendor/soved/laravel-magic-auth/ and read composer.json, the service provider, and src/. This package has no dependents and last shipped in 2020, so the source is your documentation — the README is thin and the API surface is small.php artisan vendor:publish --tag=magic-auth (or inspect boot() in the service provider for the real tag) to get config/magic-auth.php. Look for the expiry window, the user model/table, and the post-login redirect.HasMagicAuth) that you add to App\Models\User. It provides the URL generator and the notification trigger. Add it, then run php artisan config:clear before testing.show (email form) and send (validate email, trigger the link). That's the whole feature; don't try to also replace registration on day one.log or Mailhog as your mailer so you can click the link out of storage/logs/laravel.log. Test with php artisan route:list to see which routes the provider registered — you need to know the exact URI and middleware before you can protect or rate-limit it.Standard email → link → session flow. A POST /magic-login action validates the email, looks up the user, and calls the trait's send method. The generated link hits the package's handler route, which authenticates and redirects. Keep your own controller thin and let the package own the callback route.
Never reveal whether the account exists. The send action should always return the same 200/"check your inbox" response, whether the user was found or not. Only call the notification when the user exists, and swallow the branch in your response. This is the single most common security regression in magic-link implementations.
Coexist with passwords rather than replacing them. Add a "email me a login link" affordance to your existing login screen. Users on shared machines, or with password managers, will still want the password path. This also gives you a fallback if the mail pipeline degrades.
Layer throttling at the route. Put throttle:5,1 on the send endpoint (per email and per IP if you can — Laravel's default is IP-only). Without it the endpoint is an email-bombing and account-enumeration oracle. Pair it with the package's own expiry setting, and keep expiry short — 10–15 minutes is the sane range.
Customize the notification, not the internals. Publish or extend the notification class and override the mail subject/line and the URL TTL in one place. If the config lets you swap the notification class, do that — it survives package updates better than editing vendor files.
Queue the notification. Implement ShouldQueue on your subclass (or set the queue in config) so the HTTP request doesn't block on SMTP. This matters more than usual because the link must arrive while the token is still valid.
Handle the post-login redirect explicitly. Magic links often land users on a deep-link intent (e.g., the page they were trying to reach). Store intended in the session before sending, and let the package's redirect hit redirect()->intended().
SPA / stateless variant. If you have a separate frontend, have the magic link route authenticate and then redirect to your SPA with a short-lived signed exchange token, rather than trying to share the session cookie. Don't return a plain API token from a URL that also lands in the browser history.
composer require conflicts, fork it, widen the illuminate/* constraint, and fix the type errors — the codebase is small enough that this is an afternoon, not a week.signed middleware has its own expires parameter; the package likely has a config value too. If they disagree, your UI will say "valid for 15 minutes" while links die at 60, or worse, live longer than advertised. Set both from one config value.magic_token column (or a cache key) that you null out on consumption. Decide whether that's a requirement before you ship.TrustProxies and URL::forceScheme('https') or every link will 403 with "invalid signature" — a confusing failure that looks like a broken package.$request->session()->regenerate() after Auth::login(). If it doesn't, wrap the callback route or fork the controller; session fixation on an auth endpoint is not negotiable.is_active / soft-deletes after the signature validates but before Auth::login(). It's easy to leave this out because the happy path works.config:cache will bite you. Any edits to config/magic-auth.php need a php artisan config:clear in dev. Publish the config in the same PR as the install so it's tracked in git and doesn't mysteriously revert.How can I help you explore Laravel packages today?