Magic Link
The magic-link method emails a single-use sign-in link. Clicking it hits the callback endpoint, which consumes the token and logs the user in — or, under the register-first policy, redirects to the register form with a verified-email token.
How It Works
sequenceDiagram
actor U as User
participant P as Login page
participant A as Auth API
participant S as Temp key store
participant E as Email
participant B as PostAuth pipeline
U->>P: enter email
P->>A: POST /login-magiclink
A->>S: store MagicLinkPayload under token key
A->>E: email callback link
U->>A: GET /magiclink-callback?token=
A->>S: consume token (single-use)
alt existing account
A->>B: authenticate → session + redirect
else new email (register-first)
A->>S: issue verified_key token
A-->>U: redirect /register?verified_key=
U->>A: submit names + verified_key
A->>B: single INSERT → session
end
- User enters their email on the magic-link page (
/auth/login-magiclinkin multi-method mode) POSTsends a JSON payload —MagicLinkPayload{email, token, return, remember}— stored under the token key, and emails the callback linkGET /auth/magiclink-callback?token=consumes the token (single-use, constant-time compare, optional IP binding)- On success the post-auth pipeline resolves or creates the user, creates the session, and redirects (
returnpayload or post-auth redirect)
Registration
Under CreateUserOnRegister a verified email with no account is redirected to {RegisterURL}?verified_key=<token> — the same read-only-email form AuthKnight and OTP use. Requires FuncUserExists (or the passwordless find-by-email fallback); missing config falls back to session-first with a Warn log.
Setup (multi-method)
mma, err := auth.NewMultiMethodAuth("/auth", []types.Method{
auth.NewOTPMethod(a),
auth.NewMagicLinkMethodFromAuth(a, nil, func(token string) string {
return "/auth/magiclink-callback?token=" + token
}),
})
mux.Handle("/auth/", http.StripPrefix("", mma.Handler()))
Routes
| Route | Behavior |
|---|---|
GET|POST /auth/login-magiclink | Email form + link-send API (secondary method path) |
GET /auth/magiclink-callback?token= | Consumes the token → session, verified_key redirect, or safe return redirect |
Notes
- The token is the store key itself — 128+ bits of entropy, single-use, TTL-bounded (
utils.MagicLinkExpiresSeconds, 15 min) BindIPoptionally binds the link to the requester's IP (off by default — proxies/mobile networks break it)- The
returnparameter is filtered byIsSafeReturnPathbefore entering the emailed link — no open redirects - Callback is
AuthenticateViaUsername-optional: without it the endpoint still verifies + redirects, reusable for password-reset and other verify-by-email flows
A complete working example is available in examples/magiclink.