Bye bye Firebase Token 👋🏻 Hello Service Accounts 🫶🏻

Carlos Daniel
4 min readNov 2, 2024

--

Photo by Shubham Dhage on Unsplash

This is the English version of the original post.

The Problem

Until a few months ago, I always used the token generated by Firebase from the CLI to upload my apps’ executables to Firebase Distribution. The procedure was: from the command window, I would log into Firebase with firebase login:ci, which would generate a token like this:

1//8878yfP-b1jdQCgYIARAAGAUSNwF-L9IrAqSHHAB9JarbkcxO_jVTUtcoLWuvR0yem0GOge7HBnHoNeVUCjNHMo1efhGGQFZToOY

I would save this token in my Github Actions secrets, and when my workflows called my Fastlane lanes to upload to Firebase, the executable would upload without any problem and without having to regenerate the token.

Then came a day when my workflows would fail when trying to upload to Firebase, usually with errors like:

🔐 Authenticating with FIREBASE_TOKEN environment variable
[15:52:14]: ❌ Error in Firebase App Distribution: App Distribution could not generate credentials from the refresh token specified.
Refresh token used: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX7ZdC0" (redacted)
Authorization failed. Server message:
{
"error": "invalid_grant",
"error_description": "reauth related error (invalid_rapt)",
"error_uri": "https://support.google.com/a/answer/9368756",
"error_subtype": "invalid_rapt"
}
Response status: 400 ⁠

It Got Worse

And when regenerating the token and replacing it in the secrets, the process would work, but it became exhausting to have to do this every time I wanted to generate a version automatically, as the process was no longer automatic. invalid_rapt is a clear message indicating that I needed to use a more robust authentication process.

Thus, the most common solution is to use the Google Service Account-based authentication approach instead of the Firebase token. It’s a solution that doesn’t expire, is more secure for the CI/CD process, and is currently the recommended method by Firebase. Therefore, I changed how I authenticate in Firebase for my projects, and that’s what I’ll share with you quickly.

The New Process :)

First, go to the project settings and select the Service accounts option.

Firebase console: Cuentas de servicio

There, we’ll find the option to “Generate new private key”:

Click on Generate key and save the generated JSON:

I like to encode the contents of these files (in fact, it’s suggested), so after downloading it, what I do is encode it in base64, and the new content is what I upload as a secret to Github:

Github Settings — Secrets and variables

To do this, we go to the project Settingsin Github > Secrets and variables > Actions and add it:

New Action secret

Now, we can reference this secret from our workflow files as follows: in the jobs of my workflow yaml file, in the environment variables section, we reference the created secret and assign it to the FIREBASE_SERVICE_ACCOUNT_JSON variable.

We decode its content and create the service-account.json file and place it in a path in our project so that when it’s packaged, it can access the authentication permissions to upload to App Distribution:

      - name: Prepare Staging Env Variables
env:
# other variables
FIREBASE_SERVICE_ACCOUNT_JSON: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_JSON_STAGING }}
run: |
mkdir -p path/to/put/service-account.json
echo $FIREBASE_SERVICE_ACCOUNT_JSON | base64 --decode > android/fastlane/firebase/service-account.json
## not a must but we can setup permissions and a check
chmod 644 path/to/put/service-account.json
ls -la path/to/put/service-account.json

Then, in the android Fastfile, in the firebase_app_distributionlane, we add the service_credentials_fileoption referencing the path we defined in the workflow.

firebase_app_distribution(
app: "my_app-id",
android_artifact_type: "APK",
android_artifact_path: "#{root_path}/build/app/outputs/flutter-apk/app-release.apk",
release_notes: changelog,
groups: "internal",
service_credentials_file: "#{root_path}/path/to/put/service-account.json",
debug: true
)

With this, the service account credentials configuration is linked to the lane, and it uploads the executable without problems.

And with that, we say bye bye! to Firebase Token and welcome, hello! to Service accounts.

If you enjoyed this content, 50 claps 👏🏻 would be greatly appreciated to help this guide reach more people who need it.

--

--

Carlos Daniel
Carlos Daniel

Written by Carlos Daniel

Android & Flutter Developer. GDE for Android & Mobile Engineer.

No responses yet