Skip to content

Magic links feature

For provider setup and the constructor, see Magic links provider. This page covers configuration knobs and security notes.

Endpoints

Method Path Auth Request Response
POST /auth/magic-links/login {email} {message: "Magic link sent — check your email"}
GET /auth/magic-links/callback ?token=... cookie: MessageResponse; json: TokenResponse

TTLs

  • Request token TTLMagicLinksProvider(max_age=...) controls how long the request token is valid (default 900s = 15 min). Stored under token_type="magic_link_login_request".
  • Refresh token TTL after sign-in — defaults to jwt.refresh_token_ttl (30 days).

Combining with credentials

The canonical pattern is to offer both credentials and magic links so users who can't reach their password manager still have a path in:

providers=[
    CredentialsProvider(),
    MagicLinksProvider(),
],

Users created via magic links have hashed_password=None. If they later set a password (via your own UI + adapter.set_hashed_password, or a "set password" flow you build), they can sign in either way.

Security notes

  • Tokens are hashed. The raw token in the URL is never stored. The DB stores sha256(raw).
  • One-time use. consume_token is atomic — replaying a clicked link is rejected.
  • Auto-registration opens account creation to any email that controls the inbox. Gate if needed (see provider page).
  • allow_signin gates the callback. Credentials login does not call this hook.
  • on_signin JSON-mode-only caveat. See Hooks. Audit accordingly.

When token_delivery="cookie", the magic-link callback sets access, refresh, and csrf cookies and returns {"message": "Authentication successful"} instead of a token pair. This pairs well with a browser flow where the user clicks the link directly.

Common mistakes

  • No email arrivesemail_transport is None (silent). Use ConsoleTransport in dev.
  • base_url left at default — the link points at localhost:8000. Set base_url to your public origin.
  • ConfigError: token_adapter is required for magic linksMagicLinksProvider.send_login_request raises on the first login attempt if token_adapter is None.