---
title: "Move users without resetting their · Agent Wranglers"
url: https://agentwranglers.se/playbook/codebase-takeover/leaving-an-ai-builder/move-users-with-hashes
id: TKO-18
level: Recommended
applies: accounts
updated: 2026-10-22
tokens: 963
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Move users without resetting their passwords

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Leaving an AI builder](https://agentwranglers.se/playbook/codebase-takeover/leaving-an-ai-builder.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: TKO-18
- Level: Recommended
- Chapter: [Leaving an AI builder](https://agentwranglers.se/playbook/codebase-takeover/leaving-an-ai-builder.md)
- Rule: 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.
- 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.
- Applies when: The project has user accounts.
- How: 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](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/password-storage.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
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

```python
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
```

## Sources

- [OWASP Password Storage Cheat Sheet on upgrading legacy hashes](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#upgrading-legacy-hashes)
- [Firebase on importing users](https://firebase.google.com/docs/auth/admin/import-users)

## Related rules

- SEC-21 [Store passwords with a slow hash](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/password-storage.md) in Adversarial testing

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/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.

- Previous: [Compare old and new answers before switching a route](https://agentwranglers.se/playbook/codebase-takeover/leaving-an-ai-builder/shadow-compare.md)
- Next: [Switch off the builder app on a set date](https://agentwranglers.se/playbook/codebase-takeover/leaving-an-ai-builder/switch-off-builder.md)
- [Leaving an AI builder](https://agentwranglers.se/playbook/codebase-takeover/leaving-an-ai-builder.md)
