Firebase App Distribution Service Account
This guide explains how to create a Firebase service account for automated app distribution with MobileCtl.
One Service Account for Firebase & Play Console
Good news! You can use the same service account for both Firebase App Distribution and Google Play Console. No need to create separate credentials - just set up proper permissions for both services.
See also: Google Play Service Account
Overview
A Firebase service account enables:
- Upload APK/AAB files to Firebase App Distribution
- Distribute builds to testers
- Manage release notes
- Add testers to groups programmatically
- Bonus: Can also be used for Google Play Console deployment!
Prerequisites
Before you begin, make sure you have:
- Firebase project created
- Firebase App Distribution enabled
- Firebase Console access with Owner or Editor permissions
- Your app registered in Firebase
Step 1: Enable Firebase App Distribution
1.1 Create Firebase Project (if needed)
- Go to Firebase Console
- Click Add project (or select existing project)
- Enter project name and follow the setup wizard
- Click Create project
1.2 Add Your App
- In Firebase Console, select your project
- Click the Android icon (or iOS) to add your app
- Enter your Android package name (e.g.,
com.example.myapp) - Enter App nickname (optional)
- Click Register app
- Download
google-services.json - Click Continue and Finish
1.3 Enable App Distribution
- In the left menu, click Release & Monitor → App Distribution
- Click Get started (if first time)
- Accept the terms of service
Step 2: Create Service Account
2.1 Open IAM Settings
- In Firebase Console, click the gear icon (⚙️) next to Project Overview
- Click Project settings
- Go to the Service accounts tab
- Click Manage service account permissions (opens Google Cloud Console)
2.2 Create Service Account in GCP
In Google Cloud Console:
Click + CREATE SERVICE ACCOUNT
Fill in the details:
- Service account name:
firebase-mobilectl(or any name) - Service account ID: Auto-generated (e.g.,
firebase-mobilectl@your-project.iam.gserviceaccount.com) - Service account description:
Service account for Firebase App Distribution with MobileCtl
- Service account name:
Click CREATE AND CONTINUE
2.3 Assign Roles
On the Grant this service account access to project step:
Click Select a role
Search for and add the required role:
- Firebase App Distribution Admin (required for Firebase)
Optional but recommended: If you want to use this service account for Google Play Console too:
- You don't need additional GCP roles
- Just grant Play Console permissions later (see note below)
Click CONTINUE
Click DONE
Role Options
For Firebase only:
- Firebase App Distribution Admin: Can upload builds and manage testers (minimum required)
- Firebase Admin: Full Firebase access (includes all features)
For Firebase + Play Console (same service account):
- Firebase App Distribution Admin: Required for Firebase
- No additional GCP roles needed - Play Console permissions are granted separately in Play Console itself
Using for Both Firebase and Play Console?
If you plan to use this service account for both Firebase and Play Console:
- Create it here with Firebase App Distribution Admin role
- Download the JSON key (next step)
- Then follow Google Play Service Account guide Step 4 to grant Play Console permissions
- Use the same JSON file for both destinations in your config!
Step 3: Generate JSON Key
3.1 Create Key
- In the Service Accounts list, find your newly created service account
- Click on the service account email
- Go to the KEYS tab
- Click ADD KEY → Create new key
- Select JSON format
- Click CREATE
The JSON key file will automatically download.
Keep It Secret!
This JSON file grants admin access to your Firebase project. Never commit it to version control!
3.2 Rename and Store Key
Rename the file for clarity:
# Move to credentials directory
mkdir -p credentials
# Rename downloaded file
# If using for BOTH Firebase and Play Console, use a generic name:
mv ~/Downloads/your-project-abc123-1234567890ab.json credentials/google-service-account.json
# Or if using for Firebase only:
mv ~/Downloads/your-project-abc123-1234567890ab.json credentials/firebase-service-account.json
# Set restrictive permissions
chmod 600 credentials/google-service-account.jsonNaming Recommendation
If using for both Firebase and Play Console, name it generically:
google-service-account.json(recommended)android-deployment-sa.jsonfirebase-play-console-sa.json
This makes it clear it works for multiple Google services.
3.3 Also Download google-services.json
You'll also need your app's google-services.json:
- In Firebase Console, go to Project settings
- Scroll down to Your apps
- Find your Android app
- Click the google-services.json download button
- Save it to your app directory:
# Android project
cp ~/Downloads/google-services.json app/Step 4: Set Up Test Groups
Create tester groups for organized distribution:
4.1 Create Groups
- In Firebase Console, go to App Distribution
- Click the Testers & Groups tab
- Click Add group
- Enter group name:
qa-team,beta-testers,internal, etc. - Click Create group
4.2 Add Testers
- Click on a group name
- Click Add testers
- Enter email addresses (one per line or comma-separated)
- Click Add testers
Common groups:
qa-team- Internal QA testersbeta-testers- External beta testersinternal- Company employeespartners- Partner organizations
Step 5: Configure MobileCtl
5.1 Firebase Only Configuration
# mobileops.yaml
deploy:
android:
firebase:
enabled: true
service_account: credentials/firebase-service-account.json
google_services: app/google-services.json
release_notes: "Automated build from MobileCtl"
test_groups:
- qa-team
- beta-testers5.2 Firebase + Play Console (Recommended!)
Use the same service account for both destinations:
# mobileops.yaml
deploy:
android:
firebase:
enabled: true
service_account: credentials/google-service-account.json # Same file!
google_services: app/google-services.json
test_groups:
- qa-team
- internal
play_console:
enabled: true
service_account: credentials/google-service-account.json # Same file!
package_name: com.example.yourapp
track: internalOne Credential, Multiple Destinations
If you granted both Firebase and Play Console permissions to your service account, you can use the same JSON file for both deployment destinations. This simplifies credential management!
To add Play Console permissions: Follow Step 4 of the Play Console guide
5.3 Test Configuration
# Build your app
mobilectl build android
# Deploy to Firebase only
mobilectl deploy --platform android --destination firebase
# Or deploy to both Firebase and Play Console at once:
mobilectl deploy --platform android --destination firebase,play-consoleStep 6: Verify Setup
6.1 Check File Permissions
# Check permissions
ls -l credentials/firebase-service-account.json
# Should be: -rw------- (600)
chmod 600 credentials/firebase-service-account.json6.2 Validate JSON
# Verify JSON is valid
cat credentials/firebase-service-account.json | jq .
# Should contain:
# - type: "service_account"
# - project_id: "your-project-id"
# - private_key: "-----BEGIN PRIVATE KEY-----..."
# - client_email: "firebase-mobilectl@..."6.3 Test Upload
# Dry run
mobilectl deploy --platform android --destination firebase --dry-run
# Actual upload
mobilectl deploy --platform android --destination firebaseCheck Firebase Console → App Distribution → Releases to see your build!
Troubleshooting
Error: "Permission denied" or "403 Forbidden"
Solution:
- Verify service account has Firebase App Distribution Admin role
- Check that the role was applied correctly in GCP Console
- Wait a few minutes for permissions to propagate
- Re-download JSON key if needed
Error: "App not found in Firebase project"
Solution:
- Verify your app is registered in Firebase Console
- Check that package name matches in:
mobileops.yamlgoogle-services.json- Firebase Console app registration
- Ensure App Distribution is enabled
Error: "Invalid google-services.json"
Solution:
- Re-download
google-services.jsonfrom Firebase Console - Verify it's placed in correct location (usually
app/) - Check JSON is valid:
cat app/google-services.json | jq . - Ensure it matches your app's package name
Error: "Test group not found"
Solution:
- Create the test group in Firebase Console → App Distribution
- Verify group name spelling matches exactly
- Check that group has at least one tester
- Use comma-separated list in YAML:
test_groups: [group1, group2]
Error: "Service account key expired"
Solution:
- Service account keys don't expire by default
- Check if key was manually revoked in GCP Console
- Generate a new key
- Update
mobileops.yamlwith new key path
Advanced Configuration
Custom Release Notes
Use dynamic release notes:
deploy:
android:
firebase:
release_notes: "Build ${version} - ${date}"
# Or use file:
release_notes_file: RELEASE_NOTES.txtMultiple Test Groups
Deploy to different groups:
deploy:
android:
firebase:
test_groups:
- qa-team # Internal QA
- beta-testers # External beta
- partners # Partner companies
- executives # Company leadershipConditional Deployment
Use flavor-specific Firebase apps:
deploy:
android:
firebase:
# Free flavor to one Firebase app
free:
service_account: credentials/firebase-free.json
google_services: app/src/free/google-services.json
# Paid flavor to different Firebase app
paid:
service_account: credentials/firebase-paid.json
google_services: app/src/paid/google-services.jsonSecurity Best Practices
1. Never Commit Credentials
Add to .gitignore:
# .gitignore
credentials/
**/google-services.json
*.json
!package.json
!tsconfig.json2. Restrict Service Account Permissions
Use principle of least privilege:
✓ Firebase App Distribution Admin (minimum required)
✗ Don't use "Owner" role (too broad)
✗ Don't use "Editor" role (unnecessary)3. Rotate Keys Periodically
# Every 90 days:
# 1. Create new key in GCP Console
# 2. Update mobileops.yaml
# 3. Test deployment
# 4. Delete old key4. Use Environment Variables in CI/CD
Don't store JSON in repo:
# .github/workflows/deploy.yml
- name: Deploy to Firebase
env:
FIREBASE_SA: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
run: |
echo "$FIREBASE_SA" > /tmp/firebase-sa.json
mobilectl deploy --platform android --destination firebase5. Monitor Service Account Activity
Check usage regularly:
- GCP Console → IAM & Admin → Service Accounts
- Click service account
- View activity logs
- Review for suspicious activity
CI/CD Integration
GitHub Actions
# .github/workflows/deploy.yml
name: Deploy to Firebase
on:
push:
tags:
- 'v*'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Build APK
run: ./gradlew assembleRelease
- name: Deploy to Firebase
env:
FIREBASE_SERVICE_ACCOUNT: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
GOOGLE_SERVICES: ${{ secrets.GOOGLE_SERVICES_JSON }}
run: |
echo "$FIREBASE_SERVICE_ACCOUNT" > /tmp/firebase-sa.json
echo "$GOOGLE_SERVICES" > app/google-services.json
mobilectl deploy --platform android --destination firebase -yAdd secrets in GitHub:
- Settings → Secrets → New repository secret
- Name:
FIREBASE_SERVICE_ACCOUNT - Value: Paste entire JSON content
- Repeat for
GOOGLE_SERVICES_JSON
GitLab CI
# .gitlab-ci.yml
deploy_firebase:
stage: deploy
image: openjdk:17
script:
- echo "$FIREBASE_SERVICE_ACCOUNT" > /tmp/firebase-sa.json
- echo "$GOOGLE_SERVICES_JSON" > app/google-services.json
- mobilectl deploy --platform android --destination firebase -y
only:
- tagsAdd variables in GitLab:
- Settings → CI/CD → Variables
- Add
FIREBASE_SERVICE_ACCOUNTandGOOGLE_SERVICES_JSON - Check Protect variable and Mask variable
Multiple Apps / Flavors
Separate Firebase Projects
deploy:
android:
firebase:
# Production app
production:
service_account: credentials/firebase-prod.json
google_services: app/src/production/google-services.json
test_groups: [internal, executives]
# Staging app
staging:
service_account: credentials/firebase-staging.json
google_services: app/src/staging/google-services.json
test_groups: [qa-team, developers]Same Project, Different Apps
deploy:
android:
firebase:
# Android app
android:
service_account: credentials/firebase-sa.json
google_services: app/google-services.json
# Wear OS app (separate Firebase app)
wear:
service_account: credentials/firebase-sa.json
google_services: wear/google-services.jsonRelated Documentation
- Google Play Service Account - Use same service account for Play Console!
- Deploy Command - Using Firebase deployment
- Setup Wizard - Automated credential configuration
- CI/CD Integration - Automating deployments
- Configuration Reference - All deployment options
Useful Links
Quick Reference
TL;DR for Firebase only:
- Firebase Console → Project settings → Service accounts
- Create service account in GCP with Firebase App Distribution Admin role
- Download JSON key
- Create test groups in Firebase Console
- Add to
mobileops.yaml:service_account: credentials/firebase-sa.json - Test:
mobilectl deploy --platform android --destination firebase
TL;DR for Firebase + Play Console (same service account):
- Create service account with Firebase App Distribution Admin role
- Download JSON key → save as
credentials/google-service-account.json - Grant Play Console permissions via Play Console → API access
- Use same JSON file for both in
mobileops.yaml - Test:
mobilectl deploy --platform android --destination firebase,play-console
One service account. Two destinations. Zero hassle. ✨