Magic Link Authentication
Passwordless authentication via single-use email links. Users enter their email, receive a link, and click it to log in — no password required.
How It Works
- User submits their email address
- A unique token is generated and stored in the
magic_linkstable - An email is sent with a signed login link
- Clicking the link authenticates the user and issues a Sanctum token
- The token is consumed immediately — it cannot be reused
Send Magic Link
POST /api/auth/magic-link
{
"email": "john@example.com"
}
Returns a success response regardless of whether the email exists (to prevent email enumeration).
{
"message": "If an account exists, a login link has been sent."
}
Authenticate via Magic Link
GET /api/auth/magic-link/{token}
When the user clicks the link in their email, this endpoint validates the token and returns a Sanctum token.
{
"token": "1|abc123def456...",
"user": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
}
}
Token Validation Rules
- Token must exist in the
magic_linkstable - Token must not be expired — links are valid for 15 minutes
- Token must not have been used already (
used_atmust be null)
JIT Provisioning
If the email does not belong to an existing user and registration is enabled, a new account is automatically created (Just-In-Time provisioning). The user's email is marked as verified since they proved ownership by clicking the link.
- A default name is derived from the email address
- No password is set — the user can add one later from their profile
- The
Registeredevent is fired, triggering the welcome notification
Models & Classes
MagicLink Model
The MagicLink model represents a single-use login token stored in the magic_links table.
magic_links
├── id
├── email
├── token (unique, 64-character random string)
├── used_at (nullable, set when consumed)
├── expires_at (15 minutes from creation)
├── created_at
└── updated_at
MagicLinkMail
The MagicLinkMail mailable class handles the email delivery. It uses the application's email template system and includes:
- A prominent call-to-action button with the login link
- Expiry notice (15 minutes)
- IP address of the requester for security awareness
Rate Limiting
The send endpoint is rate-limited to 5 requests per minute per email to prevent abuse. Previously generated tokens for the same email are invalidated when a new one is created.
Admin Toggle
Magic link login can be enabled or disabled from the admin panel:
- Setting:
auth.magic_link→enabledordisabled - When disabled, the
POST /api/auth/magic-linkendpoint returns403 Forbidden - Existing unexpired tokens remain valid until they expire naturally