Runbook: Admin Sign-in Fails
- Severity: Medium for one administrator; High if all administrators are blocked during an incident.
- Scope:
admin.acesense.io, private docs, and launchpad authorization.
Symptomsโ
- Firebase sign-in succeeds but an admin page reports permission denied.
- Firestore reads fail while the UI shell is visible.
- An admin callable returns
permission-denied. - Docs or launchpad returns 403 after Google sign-in.
Authorization contractโ
The preferred signal is admin: true in the Firebase ID token. During the
migration, the verified-email allowlist remains a fallback. Unverified email,
the email stored in users/{uid}, and a client-side route gate do not grant
access.
Direct Firestore/Storage reads and callable invocations are separately enforced, so test both.
Diagnosisโ
- Confirm the Firebase project is
acesense-prodand the expected user is signed in. - Force an ID-token refresh (sign out/in is the simplest safe test).
- Inspect token claims locally or through a trusted admin tool; do not paste the token into an external decoder.
- Confirm
admin === true, or during migration confirm bothemail_verified === trueand exact membership in the canonical allowlist. - Test one Firestore read and one harmless admin callable to separate Rules from callable authorization.
- For docs/launchpad, clear only the site's
__sessioncookie and sign in again, then inspectdocsServerorlaunchpadServerlogs.
Mitigationโ
For an existing allowlisted administrator, use Admin โ Settings โ Admin Claims โ Set admin claims. This invokes the audited bootstrap callable and is idempotent. The affected user must refresh their ID token afterward.
If no admin can reach Settings, run the reviewed
acesense-auth-function/scripts/grant-admin-claim.ts with Application Default
Credentials that hold Firebase Auth admin permission. Do not add a broad email
domain or make the private sites public as a workaround.
Adding an administrator during migrationโ
Follow Admin Allowlist. Until the email fallback is removed, update every mirrored enforcement list and its tests in one change, deploy the affected rules/functions, grant the claim, and verify with a fresh token.
Resolution checksโ
- Admin route loads and a read-only data view succeeds.
- A harmless admin callable succeeds and creates the expected
admin_auditrecord. - A non-admin account remains denied by Rules, callables, docs, and launchpad.
- An unverified token using an allowlisted address remains denied.
- The claim/allowlist copies match the canonical compliance page.
Write a postmortem if the lockout affected incident response or was caused by a rules/auth deployment.