Skip to main content
You cannot convert a password hash without the password, so you do not try. Keep the old hash, check it when the user signs in, and write a new hash while you have the plaintext in hand.
On a correct password the hash is replaced with theAuth’s PBKDF2 hash, a migrated record is written, and onLegacyHashAccepted runs with the user id and the old algorithm name. Never the password. If the rehash fails, or your hook throws, the login still succeeds. The old hash stays and the next login tries again.

What is supported

Without a verifier for bcrypt or argon2, verify returns an error with code VERIFIER_MISSING and the user should be sent through a password reset.

Safety notes

  • Hash comparisons are constant time.
  • PBKDF2 iteration counts above 5 million and scrypt memory above 256 MB are refused, so a bad row in an import cannot be used to tie up your server.
  • A wrong password never changes the stored hash and never calls the hook.
  • Unknown hash formats return UNKNOWN_HASH rather than guessing.

Using it with the username module

The username module checks PBKDF2 only. Call passwords.verify yourself in your sign-in route for users that still have an imported hash, then create the session as usual. Users who have already been upgraded verify through the same call, so you can use it for everyone.
Last modified on October 9, 2026