Firebase Emulator Testing โ Phone+PIN Flows โ
Last Updated: 2026-03-17
Guide for testing Phone+PIN authentication, email encryption, phone recycling, and recovery backup flows using the Firebase Emulator Suite.
Prerequisites โ
- Node.js 22+
- Firebase CLI installed (
npm install -g firebase-tools) .env.localconfigured (copy from.env.local.example)
1. Setup โ
Enable Emulator Connections โ
Add to your .env.local:
VITE_USE_EMULATORS=trueThis tells the frontend to connect to local emulators instead of the real Firebase project. Remove or clear this value when you want to use the real backend.
Emulator Secrets โ
Cloud Functions that use secrets (email encryption, Resend API) need a .secret.local file in the functions directory:
# services/functions/firebase/.secret.local
RESEND_API_KEY=re_test_fake_key_for_emulator
EMAIL_ENCRYPTION_KEY=<any-64-char-hex-string>Generate a test encryption key:
python3 -c "import secrets; print(secrets.token_hex(32))"Note:
.secret.localis gitignored and must never be committed.
2. Starting the Emulators โ
Quick Start โ
npm run emulators # Kills stale ports, starts auth + functions + firestoreIndividual Commands โ
npm run emulators:kill # Kill processes on emulator ports only
npm run emulators:firestore # Start firestore emulator onlyEmulator Ports โ
| Service | Port | URL |
|---|---|---|
| Auth | 9099 | http://127.0.0.1:9099 |
| Functions | 5001 | http://127.0.0.1:5001 |
| Firestore | 8080 | http://127.0.0.1:8080 |
| Emulator UI | 4000 | http://127.0.0.1:4000 |
| Hub | 4400 | http://127.0.0.1:4400 |
Start the Dev Server โ
In a second terminal:
npm run devOpen http://localhost:5173. You should see ๐ง Firebase Emulators connected in the browser console.
3. Testing Phone+PIN Signup โ
Navigate to http://localhost:5173/#/signup/phone
Step 1 โ Phone Number + Age โ
- Enter a phone number (e.g.,
555-123-4567) - Check the age verification box
- Click "Continue"
Step 2 โ PIN Creation โ
- Enter a 6-digit PIN (avoid weak PINs like
123456,000000) - Confirm the PIN
- All three checks must show green: 6 digits, not common, PINs match
- Click "Continue"
Step 3 โ Email Capture (Optional) โ
- Enter an email address twice (must match)
- Or click "Skip for now"
- If provided, the
encryptUserEmailCloud Function runs on the emulator
Step 4 โ Recovery Phrase โ
- A 12-word BIP39 recovery phrase is displayed
- Copy it down โ this is the only way to recover the account if the PIN is forgotten
- Optionally click "Email encrypted backup" to test the backup flow
- Check the confirmation checkbox
- Click "Continue"
Step 5 โ Terms โ
- Accept terms to complete signup
- Account is created in the Auth emulator, profile written to Firestore emulator
Verification โ
Open the Emulator UI at http://127.0.0.1:4000:
- Auth tab: New user appears with the email used during signup
- Firestore tab โ
userscollection: Profile document with fields:phoneโ normalized phone numberphoneSalt,encryptedSeed,recoveryPhraseHashโ encryption datalanternNameโ generated display nameauthMethod: "phone_pin"encryptedEmail(if email was provided and Cloud Function succeeded)
4. Testing Phone+PIN Login โ
Navigate to http://localhost:5173/#/login/phone
- Enter the same phone number from signup
- Enter the 6-digit PIN
- Should unlock encryption and log you in
PIN Lockout โ
- Enter wrong PINs 3+ times
- A countdown lockout timer appears
- After lockout, "Reclaim this number" link appears (tests the reclaim flow)
5. Testing Phone Reclaim Flow โ
The reclaim flow handles phone number recycling (someone gets a previously-used phone number).
- At the Phone+PIN login screen, fail 3+ PIN attempts
- Click "Reclaim this number"
- A modal appears with the reclaim flow:
- Confirm step: Explains the 48-hour grace period
- Waiting step: Polls
checkPhoneReclaimStatusevery 30 seconds - Complete step: Calls
completePhoneReclaimto transfer the number
Emulator Verification โ
- Firestore โ
phoneReclaimscollection: New reclaim document with status and timestamps - Functions logs (in emulator terminal):
initiatePhoneReclaim,checkPhoneReclaimStatus,completePhoneReclaiminvocations
6. Testing Email Encrypted Backup โ
During signup step 4 (Recovery Phrase):
- Click "Email encrypted backup"
- Enter a backup password (8+ chars, must contain a letter and a number)
- Click "Encrypt & Send"
- The backup is encrypted client-side (PBKDF2 + AES-GCM), then sent via
sendRecoveryBackupEmail
Note: Emails won't actually send in the emulator (Resend API key is fake), but the Cloud Function executes and logs the attempt. Check the functions emulator output for confirmation.
7. Monitoring & Debugging โ
Emulator UI โ
Open http://127.0.0.1:4000 to:
- Auth tab โ View/manage created users, reset passwords
- Firestore tab โ Browse collections (
users,phoneReclaims), inspect documents - Functions logs โ See Cloud Function executions, errors, and
devLogoutput
Browser Console โ
Look for these indicators:
| Log | Meaning |
|---|---|
๐ง Firebase Emulators connected | Frontend is using emulators |
โ
Signup complete: {...} | Account creation succeeded |
Failed to encrypt email server-side (non-fatal) | encryptUserEmail failed (check .secret.local) |
User profile not found | Race condition during signup (harmless, resolves on reload) |
Known Emulator Behaviors โ
- Profile not found on first load โ
createUserWithEmailAndPasswordfiresonAuthStateChangedbeforesetDocwrites the profile. This is a harmless race condition. The profile loads correctly after reload. - Flash analytics 401s โ The analytics API isn't part of the emulator suite. Token validation fails for emulator users. Not an issue.
enableIndexedDbPersistencedeprecation warning โ Firebase SDK warning, safe to ignore.
8. Cleanup โ
Stop Emulators โ
Ctrl+C in the emulator terminal, or:
npm run emulators:killReset Emulator Data โ
Emulator data is ephemeral by default โ stopping and restarting clears all Auth users and Firestore documents.
Disable Emulator Connections โ
In .env.local, remove or clear the emulator flag:
VITE_USE_EMULATORS=Then restart the dev server.
See Also โ
- LOCAL_TESTING.md โ General local dev testing (passphrase flows, console commands)
- PHONE_AUTH_RESET.md โ Resetting phone auth state on the live dev project for re-testing
- PROFILE_INSPECTOR.md โ Inspect user profiles across Auth, users, and adminProfiles
- TEST_CROSS_DEVICE_SYNC.md โ Cross-device sync testing
apps/web/src/firebase.jsโ Emulator connection logicservices/functions/firebase/.secret.localโ Emulator secrets (gitignored)