Email verification
fastauth ships a verification flow that is anti-enumeration by design: the
POST /auth/send-verification-email endpoint always returns
{"success": true} regardless of whether the email is registered. The actual
token is emitted via the OtpGenerated event so tests can capture it without
parsing email bodies.
Flow
-
Caller requests verification:
-
fastauth creates a
Verificationrow, renders theverification.html/verification.txtJinja templates, and dispatches them via the configuredEmailSender. The plaintext token is bundled into the rendered link. -
The user clicks the link, which lands on your front-end's verify page and submits the token to:
-
On success the response sets a fresh session cookie — the verification flow doubles as a sign-in for the verified user.
Configuration
from fastauth import FastAuthOptions
from fastauth.options import EmailVerificationOptions
from datetime import timedelta
options = FastAuthOptions(
# ...
email_verification=EmailVerificationOptions(
expires_in=timedelta(minutes=15),
callback_path="/verify",
require_verified_for_sign_in=True,
),
)
Verification links are built from FastAuthOptions.app.base_url and
callback_path. Set callback_url_override only when the verification link
must use a different origin.
Custom email transport
Replace the default ConsoleEmailSender with your provider's adapter:
from fastauth import FastAuth
class SesEmailSender:
async def send(self, message: EmailMessage) -> None:
...
auth = FastAuth(options, email_sender=SesEmailSender())
Capturing tokens in tests
Install test_utils(TestUtilsOptions(capture_otp=True)) and read
helpers.get_otp(identifier) after triggering the verification email.