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_links table
  • 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_links table
  • Token must not be expired — links are valid for 15 minutes
  • Token must not have been used already (used_at must 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 Registered event 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_linkenabled or disabled
  • When disabled, the POST /api/auth/magic-link endpoint returns 403 Forbidden
  • Existing unexpired tokens remain valid until they expire naturally