Python FastAPI Tutorial (Part 14): Password Reset - Email, Tokens, and Background Tasks
TL;DR
This tutorial demonstrates implementing a secure password reset flow in FastAPI using cryptographically secure hashed tokens stored in a database, asynchronous email sending via aiostmplib to prevent blocking, and Jinja2 templates for HTML emails, following security best practices like one-hour expiration and single-use validation.
🔐 Security Architecture & Best Practices 3 insights
Use cryptographically secure random tokens
Tokens must be unguessable and unpredictable to prevent brute force attacks, with a best practice expiration of 60 minutes or less.
Implement single-use token validation
Reset tokens must be immediately invalidated after use to prevent replay attacks, requiring database storage rather than stateless JWTs.
Prevent user enumeration attacks
The system should not reveal whether specific email addresses exist in the database when processing reset requests.
⚡ Asynchronous Email Infrastructure 3 insights
Use aiostmplib for non-blocking SMTP
Unlike Python's synchronous smtplib, aiostmplib operates asynchronously to prevent blocking the FastAPI event loop during email transmission.
Leverage FastAPI BackgroundTasks
Email sending should be handled as background tasks to ensure API endpoints return responses immediately without waiting for SMTP operations.
Configure secure email settings
Store SMTP passwords as SecretStr in Pydantic settings to prevent accidental logging, and hardcode frontend URLs to prevent attackers from manipulating request data to redirect reset links.
📧 Email Template Architecture 3 insights
Design email-compatible HTML templates
Email templates require inline CSS and table-based layouts rather than modern CSS Grid or Flexbox, as many clients strip style tags and ignore JavaScript.
Always include plain text fallback
Construct emails with both HTML and plain text versions using Python's email.message class to ensure accessibility across all email clients.
Render templates without request objects
Use templates.env.get_template() and manually render to string since email generation occurs outside the HTTP request/response cycle.
🗄️ Database Token Strategy 3 insights
Store token hashes, not plaintext
Persist only 64-character hashes of tokens in the database so that database breaches don't compromise active reset links.
Choose database tokens over JWTs
Unlike JWTs which cannot be invalidated before expiration without complex blacklists, database-stored tokens enable true single-use behavior and immediate invalidation by deleting records.
Implement cascade deletion for cleanup
Configure SQLAlchemy relationships with cascade='all, delete-orphan' to automatically remove reset tokens when a user account is deleted.
Bottom Line
Store password reset tokens as hashed values in your database with one-hour expiration to enable immediate invalidation after use, rather than using JWTs which cannot be easily revoked.
More from Corey Schafer
View all
Python FastAPI Tutorial (Part 13): Pagination - Loading More Data with Query Parameters
This tutorial demonstrates how to implement offset-based pagination in FastAPI using skip and limit query parameters, covering backend schema design with SQLAlchemy queries and frontend integration with a 'load more' button pattern.
Python FastAPI Tutorial (Part 12): File Uploads - Image Processing, Validation, and Storage
Corey Schafer demonstrates implementing secure profile picture uploads in FastAPI using Pillow for image resizing and format standardization, with proper handling of CPU-bound tasks in async contexts and safe file transaction patterns to prevent data loss.
Python FastAPI Tutorial (Part 11): Authorization - Protecting Routes and Verifying Current User
This tutorial demonstrates how to implement proper authorization in FastAPI by creating a reusable dependency that validates JWT tokens and retrieves the current user, enabling secure route protection and ownership verification while eliminating hard-coded user IDs.
Python FastAPI Tutorial (Part 10): Authentication - Registration and Login with JWT
This tutorial establishes backend authentication infrastructure for FastAPI by implementing Argon2 password hashing, JWT token management, and Pydantic Settings configuration, while updating database models and schemas to support secure user registration and login workflows.