firebase-admin-python icon indicating copy to clipboard operation
firebase-admin-python copied to clipboard

Illegal Firebase credential provided. App must be initialized with a valid credential instance error - when using another type of `google.auth.Credential` object with the SDK.

Open LPLabrys99 opened this issue 1 year ago • 4 comments

Hi there, I am having some issues using the firebase_admin python client with a credential object from outside the SDK.

In my use case, I want to initialize the firebase_admin SDK using a Service Account impersonation credential to list users within the firebase environment.

To do this I tried the following:

import google.oauth2.credentials
import google.auth.impersonated_credentials

source_credentials = google.oauth2.credentials.Credentials(token=id_token)
credentials = google.auth.impersonated_credentials.Credentials(
    source_credentials=source_credentials,
    target_principal=my_service_account_email,
    target_scopes=target_scopes,
    lifetime=500
)

app_options = {'projectId': project_id}
firebase_app = firebase_admin.initialize_app(
  credential=firebase_credential, options=app_options)

When running initialize_app it returns an exception - Illegal Firebase credential provided. App must be initialized with a valid credential instance.

Looking into the firebase-admin-python source code I was able to find the source of the problem. In firebase_admin/__init__.py line 209 the code checks whether the supplied credentials object is an instance of firebase_admin.credentials.Base. If not, then the SDK returns the exception.

I don't understand why this is the case. Why does firebase-admin-python have its own credentials class which seems to just wrap google.oauth2.credentials objects? Why wouldn't the Firebase SDK accept a google.oauth2.credentials object directly?

I was able to work around it by hacking the ApplicationDefault class that comes with the firebase-admin-python SDK, however this seems a bit backwards.

firebase_credential = firebase_admin.credentials.ApplicationDefault()
firebase_credential._g_credential = credentials
firebase_credential._project_id = SOURCE_PROJECT

In my opinion it would be better if the firebase SDK just made use of the google.auth module which has a much better implementation.

LPLabrys99 avatar May 04 '23 15:05 LPLabrys99

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

google-oss-bot avatar May 04 '23 15:05 google-oss-bot

I'm running into the same issue of firebase_admin not accepting impersonated_credentials.Credentials, is there an ETA for when this might be fixed?

luka-mikec avatar Nov 18 '23 14:11 luka-mikec

Has anyone figured out another solution?

dinvlad avatar Jan 04 '24 17:01 dinvlad

The illegal credential issue is caused by this check.

I was trying to initialize with anonymous credentials for some unit/integration tests, and ended up with this:

from firebase_admin import credentials
from google.auth.credentials import AnonymousCredentials


class _OfflineGCPCredentials(credentials.Base):
    def get_credential(self):
        return AnonymousCredentials()

My guess is you should be able to put the creation of the impersonated credentials in the get_credentials method. I think that would be better than using the private API (directly updating _g_credential, _project_id, etc).

I agree with the initial issue though - I can't see why the API won't accept google.auth credentials directly. Adding the check for the base class google.auth.credentials.Credentials, and wrapping it with a firebase_admin.credentials.Base seems like an easy win.

CoatedMoose avatar Aug 20 '24 19:08 CoatedMoose