Better Auth in Rust

Password Management

Forget, reset, and change passwords.

The PasswordManagementPlugin provides endpoints for password reset flows, password changes, and current-password verification.

Password reset and change use AuthConfig.password.min_length and max_length, which default to 8 and 128 UTF-16 code units. The default hasher applies NFKC normalization before hashing and verification. Custom PasswordHasher implementations receive the original password.

Reset tokens are consumed atomically. Concurrent requests using one token can reset the password only once. An invalid password length does not consume the token.

Before upgrading an existing installation, identify password hashes created from non-NFKC input. Those users must reset their passwords; default verification does not retry the previous unnormalized input.

Setup

These examples assume you've already defined AppAuthSchema. If you want a complete setup from entity definitions through Axum mounting, start with the Axum integration guide.

use std::sync::Arc;

use better_auth::plugins::{
    PasswordManagementPlugin,
    password_management::SendResetPassword,
};

struct ResetSender;

#[async_trait::async_trait]
impl SendResetPassword for ResetSender {
    async fn send(
        &self,
        user: &serde_json::Value,
        url: &str,
        token: &str,
    ) -> better_auth::AuthResult<()> {
        let _ = (user, url, token);
        Ok(())
    }
}

let auth = BetterAuth::<AppAuthSchema>::new(config)
    .store(store)
    .plugin(
        PasswordManagementPlugin::new()
            .reset_token_expiry_hours(24)
            .require_current_password(true)
            .send_reset_password(Arc::new(ResetSender))
    )
    .build()
    .await?;

Plugin Options

OptionTypeDefaultDescription
reset_token_expiry_hoursi6424Hours before reset token expires
require_current_passwordbooltrueRequire current password for changes
send_email_notificationsbooltrueSend email on password changes

Forget Password

Initiates a password reset flow.

This endpoint requires PasswordManagementPlugin::send_reset_password(...). Configuring a global EmailProvider alone does not enable POST /request-password-reset.

POST /request-password-reset
Content-Type: application/json
{
  "email": "[email protected]",
  "redirectTo": "https://example.com/reset"
}

Response

{
  "status": true
}

Always returns success regardless of whether the email exists (prevents enumeration).

Reset Password

Completes the password reset using a token from the email link.

POST /reset-password
Content-Type: application/json
{
  "newPassword": "new_secure_password",
  "token": "reset_token_from_email"
}

Response

{
  "user": { ... }
}
StatusCondition
400Token missing or expired, password too short

Validate Reset Token

Check if a reset token is still valid before showing the reset form.

GET /reset-password/{token}

Returns 200 if valid, 400 if expired or invalid.

Change Password (Authenticated)

Change password for the currently signed-in user.

POST /change-password
Authorization: Bearer <token>
Content-Type: application/json
{
  "currentPassword": "old_password",
  "newPassword": "new_password",
  "revokeOtherSessions": "true"
}
FieldRequiredDescription
currentPasswordYesCurrent password for verification
newPasswordYesNew password (must meet policy)
revokeOtherSessionsNoRevoke all other sessions after change

Response

{
  "user": { ... },
  "token": "session_new..."
}

Verify Password (Authenticated)

Verify the current user's password before a sensitive action.

POST /verify-password
Authorization: Bearer <token>
Content-Type: application/json
{
  "password": "current_password"
}

Response

{
  "status": true
}

For users without a credential password, this endpoint returns the same Invalid password error as an incorrect password.

On this page