You run firebase deploy locally or in CI and it errors:
Error: HTTP Error: 403, The caller does not have permission
Error: Request to https://firebase.googleapis.com/... had HTTP Error: 403
Or more bluntly:
Error: Failed to authenticate, have you run firebase login?
The fix isn’t in the firebase deploy command — it’s in the identity chain behind it: your local Google account → project mapping → that account’s IAM roles on GCP. Any link missing = permission denied.
Common causes
Ordered by hit rate, highest first.
1. Logged into personal account, project is under work account
Most common. firebase login defaulted to personal@gmail.com, but the project is in you@company.com’s GCP organization — personal account has zero access.
How to spot it: firebase login:list shows current account; compare to which org/account owns the project in GCP console.
2. Account lacks Firebase Hosting Admin role
Account can see the project but can’t deploy. Common for new hires — SRE added Viewer but forgot the deploy roles.
How to spot it: GCP IAM → select project → find your email → review role list.
3. Wrong project ID in .firebaserc
{
"projects": {
"default": "my-project-prod" // real ID is my-project-prod-x9q
}
}
CLI tries to deploy to a project that doesn’t exist or you can’t access.
How to spot it: firebase projects:list to see what you can access; compare to .firebaserc.
4. CI uses expired / wrong service account key
CI auth via GOOGLE_APPLICATION_CREDENTIALS or FIREBASE_TOKEN. Key was deleted, rotated, or had permissions revoked.
How to spot it: CI logs 401/403, local deploy of the same project works.
5. Required API not enabled
Cloud Build API / Cloud Functions API / Cloud Run API disabled. CLI prompts to enable, but nobody confirms in CI.
How to spot it: Error contains “API has not been used” or “is disabled.”
6. Org policy blocks personal accounts
Some GCP orgs enforce “External members not allowed” — gmail.com accounts can be invited but not deploy.
How to spot it: Error contains “principalType is not allowed by the organization policy.”
Shortest path to fix
Step 1: Audit the identity chain
# 1. Current account
firebase login:list
# 2. Projects this account can access
firebase projects:list
# 3. Active project alias from .firebaserc
cat .firebaserc
# 4. Active deploy target
firebase use # shows current
Cross-check: account → project visible in the list → .firebaserc ID present in the list → use is the intended target.
Step 2: Log in with the right account
firebase logout
firebase login # pick work account in browser
firebase login:list # confirm work email
For multi-account switching, use --account:
firebase deploy --account=you@company.com --project=my-prod
Step 3: Have admin add IAM roles
Minimum for Hosting + Functions deploy:
- Firebase Hosting Admin (roles/firebasehosting.admin)
- Cloud Functions Admin (roles/cloudfunctions.admin)
- Service Account User (roles/iam.serviceAccountUser)
- Firebase Admin (roles/firebase.admin) # blunt all-in-one
Admin goes to IAM → project → Grant Access → add your email + the roles.
Step 4: Fix .firebaserc
firebase use --add # interactive picker
# or edit by hand:
{
"projects": {
"default": "my-project-prod-x9q",
"staging": "my-project-staging-a3p"
}
}
firebase use staging # switch to staging
firebase deploy --only hosting
Step 5: CI uses a service account
Never run firebase login with a personal account in CI. Create a service account:
# 1. GCP IAM → Service Accounts → Create
# 2. Grant the SA the roles above
# 3. Download JSON key
# CI (GitHub Actions example)
env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GCP_SA_KEY }}
steps:
- run: |
echo "${GOOGLE_APPLICATION_CREDENTIALS}" > /tmp/sa.json
export GOOGLE_APPLICATION_CREDENTIALS=/tmp/sa.json
firebase deploy --project my-project-prod --non-interactive
Or FIREBASE_TOKEN (legacy):
firebase login:ci # generate token, store in CI secret
firebase deploy --token "$FIREBASE_TOKEN"
Step 6: Enable required APIs
gcloud services enable \
firebase.googleapis.com \
cloudfunctions.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
--project=my-project-prod
Or visit API Library and enable them all.
Prevention
- Wiki page on day-one onboarding: “deploying Firebase requires these IAM roles”
- Personal projects → personal Google account; work → work — never mix; use browser profile isolation
- Commit
.firebasercwith comments per project ID (which env) - Always use a service account in CI; never personal token
- Rotate service-account keys every 90 days; calendar it
- Prefer
firebase use staging --reloadover manual.firebasercedits — more reproducible - Dry-run before deploy:
firebase deploy --only hosting --dry-runshows what would change