Magic Links
Magic links provide passwordless authentication. Users click a link in their email to log in — no password needed. AuthFort handles token generation and verification; you handle email delivery via event hooks.
How It Works
Section titled “How It Works”-
Request a magic link
Via the built-in endpoint:
POST /auth/magic-link Content-Type: application/json {"email": "user@example.com"}POST /auth/magic-link Content-Type: application/json {"email": "user@example.com"}Always returns 200 regardless of whether the email exists (prevents enumeration).
Or programmatically:
token = await auth.create_magic_link_token(email) # Returns token string, or None if user not foundtoken = await auth.create_magic_link_token(email) # Returns token string, or None if user not found -
Deliver the link
Use the
magic_link_requestedevent hook:@auth.on("magic_link_requested") async def send_magic_link(event): await send_email( to=event.email, body=f"https://myapp.com/auth/magic?token={event.token}", )@auth.on("magic_link_requested") async def send_magic_link(event): await send_email( to=event.email, body=f"https://myapp.com/auth/magic?token={event.token}", ) -
Verify and login
Via the built-in endpoint:
POST /auth/magic-link/verify Content-Type: application/json {"token": "..."}POST /auth/magic-link/verify Content-Type: application/json {"token": "..."}Returns an
AuthResponsewith tokens and user data. Sets cookies automatically if cookie mode is enabled.Or programmatically:
result = await auth.verify_magic_link(token) # Returns AuthResponse with tokens and userresult = await auth.verify_magic_link(token) # Returns AuthResponse with tokens and user
Auto-Signup
Section titled “Auto-Signup”By default, magic links only work for existing users. Set allow_passwordless_signup=True to auto-create accounts:
auth = AuthFort(
database_url="...",
allow_passwordless_signup=True,
) auth = AuthFort(
database_url="...",
allow_passwordless_signup=True,
) Email Verification
Section titled “Email Verification”Magic link login automatically sets email_verified=True — no separate verification step needed.
Security
Section titled “Security”| Property | Detail |
|---|---|
| Token lifetime | Single-use, expires after magic_link_ttl (default: 10 minutes) |
| Ban enforcement | Banned users cannot use magic links |
| Token invalidation | Requesting a new magic link invalidates any previous token |
Events
Section titled “Events”Emits magic_link_requested (includes token for delivery), magic_link_login, and optionally user_created (if auto-signup creates a new account).
See Events & Hooks for all events and their payloads.
Client SDK
Section titled “Client SDK”await auth.requestMagicLink('user@example.com');
// User clicks link in email, your app extracts the token
const user = await auth.verifyMagicLink(token); await auth.requestMagicLink('user@example.com');
// User clicks link in email, your app extracts the token
const user = await auth.verifyMagicLink(token);