Agent Wranglers

TKO-18Recommended

Move users without resetting their passwords

Export the users with their IDs and password hashes, and check each old hash at the user's next sign-in. Store a new hash then, and keep the same user ID.

How to do it

A forced reset for every user loses many of them and floods support. Most sign-in services store bcrypt or Argon2 hashes and can export them, so the new system can check the old hash once. After a correct password, hash it again with the new system's settings and drop the old hash. Keep user IDs, so every foreign key and every link still works. Sessions may end at the move, so tell users they must sign in again. Pick the new hash settings as Store passwords with a slow hash says.

Examples

JavaScript example

import bcrypt from 'bcryptjs';
import argon2 from 'argon2';

export async function verifyPassword(user, password) {
  if (user.passwordHash.startsWith('$argon2')) return argon2.verify(user.passwordHash, password);
  if (!(await bcrypt.compare(password, user.passwordHash))) return false;
  await users.update(user.id, { passwordHash: await argon2.hash(password) });
  return true;
}

Python example

import bcrypt
from argon2 import PasswordHasher

hasher = PasswordHasher()

def verify_password(user, password: str) -> bool:
    if user.password_hash.startswith("$argon2"):
        return hasher.verify(user.password_hash, password)
    if not bcrypt.checkpw(password.encode(), user.password_hash.encode()):
        return False
    users.update(user.id, password_hash=hasher.hash(password))
    return True

How to check

A test user created in the old system signs in to the new system with the same password. Afterwards their stored hash uses the new settings, and their user ID is unchanged.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/codebase-takeover/leaving-an-ai-builder/move-users-with-hashes">Agent Wranglers codebase takeover playbook</a>. In code you write, add a comment next to it with the same link.