Verify current passwords, rotate sessions, and handle social-only accounts and older valid credentials in account settings.

Changing a password from account settings requires the current password and a decision about other signed-in devices. BTST Better Auth UI supplies that form, while Better Auth validates the credentials and updates the stored password.
This guide follows @btst/better-auth-ui@2.0.1, @btst/stack@3.1.2, and better-auth@1.6.16. It covers an existing signed-in account. For a user who cannot sign in, start with the password-reset guide.
Enable email/password authentication in the existing Better Auth server. Merge these options into its existing configuration, preserving email delivery and any other auth policies:
import type { BetterAuthOptions } from "better-auth";
export const passwordPolicy = {
emailAndPassword: {
enabled: true,
minPasswordLength: 8,
maxPasswordLength: 128,
},
} satisfies BetterAuthOptions;
These lengths match the pinned release's defaults; they are not a recommendation to lower an existing policy. Keep stronger requirements already in force. Server validation remains necessary because requests can bypass the form.
The companion's matching configuration belongs in overrides.auth on the Stack provider:
import type { AuthPluginOverrides } from "@btst/better-auth-ui/client";
export const passwordUI = {
credentials: {
confirmPassword: true,
passwordValidation: { minLength: 8, maxLength: 128 },
},
} satisfies Partial<AuthPluginOverrides>;
The confirmation field checks the new password for a matching entry before submission. The auth and account plugins must already be mounted; the ordinary security route is /p/account/security. See BTST auth setup for the shared integration.
The released change-password card calls authClient.changePassword with the current password, new password, and revokeOtherSessions: true. That revocation choice is built into this component; the validation override above does not change it.
Better Auth verifies the current password on the server before saving a new hash. A successful request with revocation enabled deletes the user's existing sessions and creates a replacement for the caller, setting its cookie in the response. Custom server integrations must preserve that cookie response. Merely calling the API and discarding the updated cookie can leave the browser holding an invalidated session.
If your product needs a different session choice or a different form, implement an override while retaining current-password verification and server validation. The upstream password API documents the operation; the pinned server route establishes this release's exact behavior.
The card checks whether the account list contains providerId: "credential". Without that linked account, it displays a Set Password action instead of asking for a current password that does not exist.
In this release, Set Password starts requestPasswordReset using the current user's email and the reset-password redirect, then navigates to sign-in. It does not create a credential locally or silently assign a password. Configure the server's reset email delivery and allowed redirect before exposing that path. The reset flow's revokeSessionsOnPasswordReset policy is separate from the change-password card's hard-coded revocation choice.
Test a social-only account explicitly. Receiving an “email sent” message is not evidence that delivery succeeded or that the account now has a password. Complete the link, then verify email/password sign-in and inspect the account's actual credential state.
The card applies its passwordValidation rules to both the current-password and new-password fields. If you raise the UI minimum from eight to twelve characters, a user with a valid ten-character password can be blocked before the server sees the change request. Adding a new regular expression can cause the same problem.
The server's current-password check verifies the existing hash; its new-password length policy applies to the replacement. When tightening policy, test older valid credentials and use an appropriate form override if different rules are needed for the two fields. Do not weaken the new-password server policy to work around a form limitation. Keep a tested recovery path available.
Create two sessions for a disposable credential account, then change the password from the first. Confirm all of the following:
If cookie caching is enabled, test that last point both with ordinary reads and with the cache bypass described in the session-management guide. Previously cached session data can remain visible until its cache lifetime ends. A stale header or client-side session object is not proof that revocation failed, and immediate disappearance from a UI is not proof that a protected operation rejects the old session.
The fragments were type-checked, and in-memory handler tests cover wrong credentials, length rejection, password replacement, current-session rotation, and rejection of the other session. They do not test production mail delivery, your database migration, a complete social-provider flow, or the full account-page UI. Run the same lifecycle against your configured application before relying on it.