Email And Password Best Practices
Configure email verification, implement password reset flows, set password policies, and customise hashing algorithms for Better Auth
Category: productivity Source: better-auth/skillsWhat Is This?
Overview
Better Auth provides a robust email and password authentication system that goes beyond simple credential storage. Configuring it correctly requires attention to email verification flows, password reset mechanisms, policy enforcement, and hashing algorithm selection. Each of these components contributes to a secure and user-friendly authentication experience.
When implemented properly, the email and password module in Better Auth handles the full lifecycle of credential-based authentication. This includes verifying that users own the email addresses they register with, allowing users to recover access to their accounts, enforcing minimum password standards, and ensuring that stored credentials are protected with appropriate cryptographic methods.
Getting these configurations right from the start prevents common security vulnerabilities and reduces support overhead. Poorly configured authentication systems lead to account takeovers, weak passwords in production, and frustrated users who cannot recover their accounts. This guide covers the essential configurations and patterns needed to deploy email and password authentication responsibly.
Who Should Use This
- Backend developers integrating Better Auth into a new or existing application
- Full-stack engineers responsible for authentication architecture and security
- Security-conscious teams that need to enforce password policies across user accounts
- Developers migrating from another authentication library who need to match existing hashing behavior
- Teams building applications where email ownership verification is a compliance or business requirement
- Engineers who need to customise the user experience for password reset and verification emails
Why Use It?
Problems It Solves
- Unverified email addresses allow users to register with addresses they do not own, leading to spam accounts and failed communications
- Missing password reset flows lock users out of their accounts permanently, increasing support costs
- Weak password policies allow users to set trivially guessable credentials, exposing accounts to brute-force attacks
- Default hashing configurations may not match the security requirements or performance constraints of every deployment environment
- Inconsistent authentication flows create confusion for users and introduce edge cases that are difficult to debug
Core Highlights
- Simple one-line enablement with
emailAndPassword: { enabled: true } - Configurable email verification with custom send logic
- Built-in password reset flow with token-based verification
- Password length and complexity policy enforcement
- Support for custom hashing algorithms beyond the default
- Hooks for sending transactional emails through any provider
- Automatic token expiry management for reset and verification links
- Compatible with existing user databases when migrating from other systems
How to Use It?
Basic Usage
Enable the email and password plugin in your Better Auth configuration file:
import { betterAuth } from "better-auth";
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
minPasswordLength: 8,
maxPasswordLength: 128,
},
emailVerification: {
sendVerificationEmail: async ({ user, url }) => {
await sendEmail({
to: user.email,
subject: "Verify your email address",
body: `Click here to verify: ${url}`,
});
},
},
});
Specific Scenarios
Password Reset Flow: Configure the reset handler to send a recovery email when users request it.
emailAndPassword: {
enabled: true,
sendResetPassword: async ({ user, url }) => {
await sendEmail({
to: user.email,
subject: "Reset your password",
body: `Reset link (expires in 1 hour): ${url}`,
});
},
},
Custom Hashing Algorithm: Override the default hashing behavior to use a specific algorithm or work factor.
emailAndPassword: {
enabled: true,
password: {
hash: async (password) => myCustomHashFunction(password),
verify: async ({ hash, password }) => myCustomVerify(hash, password),
},
},
Real-World Examples
A SaaS application requiring email verification before dashboard access sets requireEmailVerification: true and gates the main application routes behind a verified status check. A financial services platform enforces minPasswordLength: 12 and integrates with SendGrid for transactional emails. A migration project from a legacy system provides custom hash and verify functions to match the existing bcrypt configuration, allowing users to log in without resetting their passwords.
When to Use It?
Use Cases
- New application setup requiring credential-based login from day one
- Adding email verification to an existing application that previously skipped it
- Replacing a custom authentication system with a maintained library
- Enforcing a new password policy across an existing user base
- Migrating users from another platform while preserving their credentials
- Building a multi-tenant application where each tenant may have different password requirements
- Compliance scenarios requiring documented password policies and verified email ownership
Important Notes
Requirements
- A configured email sending function is required for verification and reset flows to work
- The database adapter must be set up before enabling email and password authentication
- Node.js 18 or later is recommended for native crypto support used in token generation