No passwords. Just a link or a code.

Drop-in magic link and one-time code authentication for Laravel. Routes, views, emails and rate limiting included — and every piece of it swappable.

Latest
v2.2.0
Installs
115
Tests
passing
LoginController.php
config/passwordless.php
// Email a signed, single-use link:
LaravelPasswordless::for($user)->sendMagicLink();
// ...or a short one-time code:
LaravelPasswordless::for($user)->sendLoginCode();

Introduction

Getting started

Passwordless authentication for Laravel via magic links and login codes. Install it, add one trait, and your users sign in by clicking a link or typing a six-digit code.

Installation

Composer, the install wizard, and the manual path if you'd rather run each step yourself.

How it works

What happens between the send form and the authenticated session, and what lands in the database.

Configuration

Every key in config/passwordless.php, its .env equivalent, and its default.

Swapping actions

Five contracts cover token generation, authentication, and user lookup. Replace any of them.


Quick start

Three commands and one trait.

Install the package

composer require torqie/laravel-passwordless
php artisan passwordless:install

The install wizard publishes the config, publishes and runs the migrations, asks which flows you want, detects your frontend framework, and writes the answers to your .env. Full walkthrough →

Add the trait to your User model

use Illuminate\Foundation\Auth\User as Authenticatable;
use Torqie\LaravelPasswordless\Traits\HasPasswordlessAuth;

class User extends Authenticatable
{
    use HasPasswordlessAuth;
}

That is the whole setup. Routes register themselves under /auth, and the package ships working Blade views and email templates for both flows.

<a href="{{ route('passwordless.magic-link.request') }}">Sign in with a magic link</a>
<a href="{{ route('passwordless.login-code.request') }}">Sign in with a code</a>

Already have password auth?

You can run both. Nothing in this package touches your existing guard, login controller, or password column — it adds routes alongside them and logs the user in through the same guard. The published make_password_nullable_on_users_table migration is only relevant if you want to go passwordless-first and drop passwords entirely.


The two flows

Use one, the other, or both at the same time.

The user submits their email and receives a signed, time-limited URL. Clicking it authenticates them and redirects to redirects.after_login. The token is 64 random characters, hashed in the database, and single-use.

Best when the user reads mail on the same device they are signing in on. Read more →

Login codes

The user submits their email and receives a short code — six numeric digits by default. They type it on a verify form. The code is salted, hashed, and deleted the moment it is used.

Best when the sign-in device is not the mail device: a TV app, a kiosk, a phone verifying a desktop session. Read more →


What you get out of the box

  • Routes and controllers for both flows, mounted under a configurable prefix. Reference →
  • Blade views and email templates, publishable and overridable one at a time. Read more →
  • Inertia support with generated Vue, React, and Svelte stubs. Read more →
  • Rate limiting on both sending and verifying, plus silent handling of unknown email addresses so the forms do not leak which addresses have accounts. Read more →
  • Three events to hook your own logic onto. Read more →
  • Five swappable action contracts, selected by config key — no service provider bindings needed. Read more →

Requirements

DependencyVersion
PHP8.3+
Laravel12.61.1+ or 13.12.0+

Getting help

Submit an issue

Bugs, questions, and feature requests all belong on the issue tracker. For anything security-sensitive, please use the repository's security policy rather than a public issue.

Contributing

Pull requests are welcome. The package ships a full Pest suite — run composer test before opening one, and see CONTRIBUTING.md for the details.