Expo app. Firebase Auth. Email as the login. Some accounts were created as orphans: an email record with no password provider, leftover from an older import or a half-finished sign-up. If reclaim "fixed" them by writing a new password onto every match, people who already had a password got locked out of their own phone.
They type the password that worked yesterday. Firebase says invalid. Support says "we migrated you." They did not ask to be migrated. They asked to open the app.
I looked up the email with the Firebase Admin SDK. User exists. I called updateUser({ password }) so they could finish sign-up. That writes a password hash. It does not ask whether they already had one. It does not care that providerData already listed password. It just overwrites.
An orphan is a user whose providerData has no password provider. That is the only time setting a password is reclaim. Everyone else already has a credential. You send a reset link. You do not invent a new secret for them because your form had a password field.
const user = await admin.auth().getUserByEmail(email);
const hasPassword = user.providerData.some((p) => p.providerId === 'password');
if (hasPassword) {
await admin.auth().generatePasswordResetLink(email);
return { status: 'reset_sent' };
}
await admin.auth().updateUser(user.uid, { password: newPassword });
return { status: 'reclaimed' };Client sign-in stays signInWithEmailAndPassword. The orphan path is admin-only and boring. If getUserByEmail throws auth/user-not-found, create the user. Do not catch that error and updateUser a uid you do not have.
Firebase will let you overwrite a password. That is not permission. That is a footgun with an SDK.
Happy coding!
Sander