Skip to content

Phone Auth Reset โ€” Dev Testing Guide โ€‹

Last Updated: 2026-03-18

Instructions for resetting phone authentication state on a real dev Firebase project (lantern-app-dev) so you can re-test phone signup/login flows without creating a new account.

Scope: These commands hit the live dev project, not emulators. For emulator-based testing see FIREBASE_EMULATOR_TESTING.md.


Quick Script โ€‹

A single script runs all the steps below (inspect โ†’ remove phone provider โ†’ reset Firestore):

bash
# Full reset
./tooling/scripts/reset-phone-auth.sh <USER_UID>

# Inspect only (no changes)
./tooling/scripts/reset-phone-auth.sh <USER_UID> --inspect-only

Prerequisites โ€‹

  • Node.js 22+
  • firebase-admin installed (available in the repo's root node_modules)
  • Correct GOOGLE_APPLICATION_CREDENTIALS or Application Default Credentials for lantern-app-dev
  • The target user's UID (find it in Firebase Console โ†’ Authentication)

1. Remove the Phone Provider from Firebase Auth โ€‹

Strips the phone provider so the user can re-link or re-test phone signup:

bash
cd /home/mechelle/repos/lantern_app && node -e "
const admin = require('firebase-admin');
const app = admin.initializeApp({ projectId: 'lantern-app-dev' });
const UID = '<USER_UID>';
admin.auth().updateUser(UID, { phoneNumber: null })
  .then(() => console.log('Phone provider removed successfully'))
  .catch(err => console.error('Error:', err.message))
  .finally(() => app.delete());
"

Replace <USER_UID> with the target user's UID.


2. Inspect the User Document โ€‹

Check which phone/encryption fields are currently set:

bash
cd /home/mechelle/repos/lantern_app && node -e "
const admin = require('firebase-admin');
const app = admin.apps.length ? admin.app() : admin.initializeApp({ projectId: 'lantern-app-dev' });
const db = admin.firestore();
const UID = '<USER_UID>';
db.collection('users').doc(UID).get()
  .then(snap => {
    const d = snap.data();
    console.log(JSON.stringify({
      salt: d.salt || null,
      phoneSalt: d.phoneSalt || null,
      phone: d.phone || null,
      authProofHash: d.authProofHash ? '(present)' : null,
      encryptedSeed: d.encryptedSeed ? '(present)' : null,
      recoveryPhraseHash: d.recoveryPhraseHash ? '(present)' : null,
      authMethod: d.authMethod || null,
      lanternName: d.lanternName || null,
    }, null, 2));
  })
  .catch(e => console.error(e.message))
  .finally(() => app.delete());
"

3. Full Reset โ€” Revert to Passphrase-Based Login โ€‹

Removes all phone+PIN migration fields, generates a new salt, and clears encrypted data that was keyed to the old phone+PIN (now unreadable):

bash
cd /home/mechelle/repos/lantern_app && node -e "
const admin = require('firebase-admin');
const crypto = require('crypto');
const app = admin.apps.length ? admin.app() : admin.initializeApp({ projectId: 'lantern-app-dev' });
const db = admin.firestore();
const UID = '<USER_UID>';
const userRef = db.collection('users').doc(UID);

(async () => {
  const newSalt = crypto.randomBytes(16).toString('base64');

  await userRef.update({
    // Restore passphrase-based login
    salt: newSalt,
    // Remove phone+PIN migration fields
    phone: admin.firestore.FieldValue.delete(),
    phoneSalt: admin.firestore.FieldValue.delete(),
    encryptedSeed: admin.firestore.FieldValue.delete(),
    authProofHash: admin.firestore.FieldValue.delete(),
    recoveryPhraseHash: admin.firestore.FieldValue.delete(),
    encryptionMigratedAt: admin.firestore.FieldValue.delete(),
    // Clear encrypted fields (keyed to old phone+PIN, now unreadable)
    encryptedBirthDate: admin.firestore.FieldValue.delete(),
    encryptionCanary: admin.firestore.FieldValue.delete(),
    encryptionCorrupted: admin.firestore.FieldValue.delete(),
    encryptionCorruptedDetectedAt: admin.firestore.FieldValue.delete(),
  });

  console.log('Done. Account reset to passphrase-based login.');
  console.log('New salt:', newSalt);

  const snap = await userRef.get();
  const d = snap.data();
  console.log('Verify:', JSON.stringify({
    salt: d.salt ? '(present)' : null,
    phoneSalt: d.phoneSalt || null,
    phone: d.phone || null,
    role: d.role || null,
    lanternName: d.lanternName || null,
  }, null, 2));

  await app.delete();
})();
"

Important: After this reset the user must set a new passphrase on next login. Any data encrypted with the old phone+PIN key is permanently lost (by design โ€” zero-knowledge encryption).


4. Verify Encrypted Fields Were Cleared โ€‹

Quick spot-check that stale encrypted data was removed:

bash
cd /home/mechelle/repos/lantern_app && node -e "
const admin = require('firebase-admin');
const app = admin.apps.length ? admin.app() : admin.initializeApp({ projectId: 'lantern-app-dev' });
const db = admin.firestore();
const UID = '<USER_UID>';
db.collection('users').doc(UID).get().then(snap => {
  const d = snap.data();
  console.log('encryptedBirthDate:', d.encryptedBirthDate || '(not present)');
  console.log('encryptionCanary:', d.encryptionCanary || '(not present)');
  app.delete();
});
"

5. Re-Encrypt Birthday via Browser Console โ€‹

After logging back in (so the encryption key is cached in memory), you can re-encrypt and save the birthday from the browser console:

javascript
const encryption = await import('/src/lib/encryption.js');
const firebase = await import('/src/firebase.js');

const encrypted = await encryption.encryptData('1989-09-30'); // use actual birth date

const uid = firebase.auth.currentUser.uid;
const token = await firebase.auth.currentUser.getIdToken();

await fetch(
  `https://firestore.googleapis.com/v1/projects/lantern-app-dev/databases/(default)/documents/users/${uid}?updateMask.fieldPaths=encryptedBirthDate`,
  {
    method: 'PATCH',
    headers: {
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      fields: { encryptedBirthDate: { stringValue: encrypted } },
    }),
  }
);
console.log('Birthday saved');

Run this in the DevTools console on the running Lantern app (must be logged in so the encryption key is available).


Typical Reset Workflow โ€‹

  1. Remove phone provider (Step 1)
  2. Full reset to passphrase (Step 3)
  3. Verify fields cleared (Step 4)
  4. Log in with the new passphrase flow
  5. Re-encrypt birthday in browser console (Step 5)

See Also โ€‹

Built with VitePress