Skip to content

Magic Link Authentication

Magic link authentication sends a one-time login link to the user’s email. No password required — possession of the email inbox proves identity.

  1. User enters email on the auth service login page

  2. Auth service sends email with a verification link containing a one-time token

  3. User clicks link in their email

  4. Auth service verifies token, creates user if needed, issues authorization code

  5. Redirect back to the client app with the code

POST https://auth.beshoy.ai/auth/magic-link/send
Content-Type: application/json
FieldTypeRequiredDescription
emailstringYesUser’s email address
project_idstringYesTarget project
redirect_uristringYesWhere to redirect after auth
code_challengestringYesPKCE S256 challenge
statestringYesOpaque state to return
GET https://auth.beshoy.ai/auth/magic-link/verify?token=xxx

This is the link the user clicks in their email. The auth service:

  1. Retrieves the token data from KV
  2. Verifies it hasn’t expired (15-minute TTL)
  3. Creates the user if they don’t exist (unless registration is closed)
  4. Adds the user to the project if not already a member
  5. Marks the user’s email as verified
  6. Issues an authorization code
  7. Redirects to the client with code and state

Magic links are sent via the Resend email API. The email contains:

  • A branded template matching the project’s branding
  • A single call-to-action button with the verification URL
  • 15-minute expiry notice
  • 3 magic link sends per hour per email address
  • Prevents email bombing / spam

Unlike password auth, magic links can create new users automatically:

  • If registration = "open" → user created on first magic link verification
  • If registration = "invite_only" → user must already exist or have an invitation
  • If registration = "closed" → user must already exist

New users created via magic link have email_verified = 1 (since they proved inbox access).

Magic link tokens are stored in KV with:

  • Key: magic:{random_token}
  • Value: { email, project_id, redirect_uri, code_challenge, state }
  • TTL: 900 seconds (15 minutes)

Tokens are deleted after use (one-time).

ErrorCause
Rate limited3+ sends in the last hour for this email
Invalid or expired tokenToken not in KV (expired or already used)
Registration closedNew user + project registration is closed