Password Reset

Self-service password recovery with secure email links. Users can reset forgotten passwords without admin intervention.

Users can reset forgotten passwords through a secure, self-service flow. The process uses time-limited email links to verify identity.

Request Password Reset

Page location: apps/web/app/[locale]/auth/password-reset/page.tsx Route: /auth/password-reset

Password reset request form showing email input field and send reset link button

Users access this page via the "Forgot your password?" link on the sign in page. They enter their email address to receive a reset link.

Component

packages/auth/src/components/password-reset-request-container.tsx

<PasswordResetRequestContainer
redirectPath="/reset-password"
/>

Security Considerations

  • The form always shows a success message, even if the email doesn't exist (prevents email enumeration)
  • Reset tokens are single-use and time-limited
  • Previous reset tokens are invalidated when a new one is requested

Reset Email

When a password reset is requested, Better Auth:

  1. Generates a secure, random token
  2. Stores the token with an expiration time
  3. Sends an email with the reset link

Email Template

Customize the reset email at:

packages/better-auth/src/emails/send-reset-password-email.ts

export async function sendResetPasswordEmail({
email,
url,
token,
productName,
language,
}: SendResetPasswordEmailOptions) {
// Email sending logic
}

Development Mode

In development, the reset link is logged to the console:

[info] Sending password reset email...
email: user@example.com
url: http://localhost:3000/reset-password?token=...

Set New Password

Route: /reset-password

New password form showing password and confirm password fields

When the user clicks the link in their email, they're taken to a form to enter their new password.

Token Validation

The token in the URL is validated:

  1. Token exists and hasn't been used
  2. Token hasn't expired
  3. User associated with token exists

If validation fails, the user sees an error message and can request a new reset link.

Password Requirements

The new password must meet the same requirements as registration:

RequirementValue
Minimum length8 characters
Maximum length128 characters

After Reset

After successfully setting a new password:

  1. The reset token is invalidated
  2. All existing sessions for the user are optionally revoked
  3. User is redirected to the sign in page
  4. User signs in with their new password

Programmatic Password Reset

For custom flows, use the auth client:

Request Reset

'use client';
import { authClient } from '@kit/better-auth/client';
async function requestPasswordReset(email: string) {
const result = await authClient.requestPasswordReset({
email,
redirectTo: '/reset-password',
});
if (result.error) {
console.error(result.error.message);
return;
}
// Show success message
}

Complete Reset

'use client';
import { authClient } from '@kit/better-auth/client';
async function resetPassword(token: string, newPassword: string) {
const result = await authClient.resetPassword({
token,
newPassword,
});
if (result.error) {
console.error(result.error.message);
return;
}
// Redirect to sign in
window.location.href = '/auth/sign-in';
}

Configuration

Password reset is enabled automatically when email/password authentication is enabled:

packages/better-auth/src/auth.ts

emailAndPassword: {
enabled: process.env.NEXT_PUBLIC_AUTH_PASSWORD === 'true',
requireEmailVerification: true,
sendResetPassword: sendResetPasswordEmail, // Email handler
},

Token Expiration

By default, reset tokens expire after 1 hour. This is configured in Better Auth's settings.

Common Issues

"Invalid or expired token" Error

  1. Token has already been used (single-use)
  2. Token has expired (request a new one)
  3. URL was truncated or modified

Reset Email Not Received

  1. Check spam/junk folder
  2. Verify mailer configuration
  3. Ensure the email exists in the database
  4. In development, check the console for logged URLs

User Still Can't Sign In After Reset

  1. Make sure they're using the new password
  2. Check if email verification is still pending
  3. Verify the account isn't locked or banned

Previous: Sign Up ← | Next: Session Handling →