Email verification¶
Email verification uses one-time tokens stored in the token_adapter. It requires:
- a
TokenAdapter(e.g.adapter.token), - an
EmailTransportif you actually want the email delivered.
Registration does NOT send a verification email. Calling
POST /auth/registercreates the user withemail_verified=Falseand immediately issues tokens. The user must then explicitly request a verification email.
Request a verification email¶
curl -X POST http://localhost:8000/auth/request-verify-email \
-H "Authorization: Bearer $ACCESS"
# -> {"message":"Verification email sent"}
Implementation (api/auth.py): generates a one-time token of type "verification", hashes it, stores it in the token adapter with a 24-hour expiry, and calls email_dispatcher.send_verification_email(user, token, expires_in_minutes=1440). If no email_transport is configured, the email is silently not sent — but the token is still stored, so you can complete verification via the API directly.
Verify the email¶
Two equivalent endpoints:
# GET — convenient for links in emails
curl "http://localhost:8000/auth/verify-email?token=..."
# POST — convenient for SPAs
curl -X POST http://localhost:8000/auth/verify-email \
-H "Content-Type: application/json" \
-d '{"token":"..."}'
Both call _verify_email, which atomically consumes the hashed token. On success, the user's email_verified is set to True and on_email_verify is fired.
Edge cases¶
/auth/registerdoes NOT send a verification email. Documented again here because it is the #1 source of confusion./auth/loginignoresemail_verified. Unverified users can still log in — gating on verification is your application's responsibility. A common pattern isallow_signinhook +email_verifiedcheck, but note the hook reach below.allow_signinis not called by/auth/login(the credentials route). It is called by OAuth callback, magic-link callback, and passkey authenticate-complete. If you want to gate credentials login onemail_verified, do it in your own route wrapper or open an issue (see Maintainer clarification).- OAuth providers that report
email_verified=Truepropagate that to the new user on first OAuth sign-in (core.oauth.complete_oauth_flow).
Common mistakes¶
- Calling
/auth/verify-emailwith the raw email token but the endpoint returnsInvalid or expired— make sure the value sent is the raw token from the email, not the hash. - No
token_adapterconfigured —/auth/request-verify-emailreturns400 Token adapter is not configured.