Magic Link Authentication

Passwordless email link authentication

Updated Dec 29, 2025 Edit this page

Magic Link Authentication

Passwordless authentication via email link for simplified login experience.

Overview

Magic links provide a passwordless login experience:

  1. User enters email
  2. Receives email with login link
  3. Clicking link authenticates user

No password required - authentication is verified via email ownership.


Endpoints

Method Path Description
POST /api/auth/magic-link/request Request magic link
GET /api/auth/magic-link/verify Verify and authenticate

POST /api/auth/magic-link/request

Request a magic link email.

Synopsis

Property Value
Authentication Public
Rate Limit 5/minute
Token Lifetime 15 minutes

Request Body

Field Type Required Description
email string Yes User’s email address
org_slug string No Organization for branded emails

Example Request

curl -X POST https://sso.example.com/api/auth/magic-link/request \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "org_slug": "acme-corp"
  }'

Response (200 OK)

{
  "message": "If the email exists, a magic link has been sent."
}

[!NOTE] Always returns success to prevent email enumeration attacks.

Errors

Status Condition
400 Invalid email format
429 Rate limit exceeded

GET /api/auth/magic-link/verify

Verify magic link token and authenticate user.

Synopsis

Property Value
Authentication Public
Risk Assessment Yes

Query Parameters

Parameter Type Required Description
token string Yes Magic link token from email
redirect_uri string No Redirect URL after auth

Example Request

curl -X GET "https://sso.example.com/api/auth/magic-link/verify?token=magic-token-uuid"

Response - Success (200 OK)

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "refresh_token": "550e8400-e29b-41d4-a716-446655440000",
  "expires_in": 900
}

Response - High Risk (200 OK)

{
  "requires_mfa": true,
  "preauth_token": "eyJhbGciOiJSUzI1NiIs...",
  "message": "Additional verification required"
}

When requires_mfa: true, continue with MFA verification.

Errors

Status Condition
400 Invalid or expired magic link
400 User not found (must register first)
403 Blocked by risk engine

sequenceDiagram
    participant User
    participant Client
    participant AuthOS
    participant Email

    User->>Client: Enter email
    Client->>AuthOS: POST /api/auth/magic-link/request
    AuthOS->>Email: Send magic link
    AuthOS-->>Client: {message: "..."}
    Email->>User: Magic link email
    User->>AuthOS: Click link (GET /verify?token=...)
    AuthOS->>AuthOS: Risk assessment
    alt Low Risk
        AuthOS-->>Client: {access_token, refresh_token}
    else High Risk
        AuthOS-->>Client: {requires_mfa: true}
    end

Security Features

Feature Description
One-Time Use Token deleted after verification
Short Expiry 15-minute validity
Risk Assessment Evaluates IP, location, device
Device Trust Establishes 90-day trusted device cookie
Rate Limiting 5 requests per minute

Device Trust

On successful low-risk authentication, a device trust cookie is set:

Set-Cookie: device_token={signed-token}; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=7776000

Trusted devices may bypass MFA for subsequent logins.