I am trying to initialize firebase-admin
on my Flask API. Based off the documentation, the method initialize_app
can take a dictionary as an input as seen here:
That said, I structured my code as follows:
import firebase_admin
from firebase_admin import auth, credentials
...
firebase_admin.initialize_app({ \
credentials.Certificate({ \
"type": "service_account", \
"project_id": os.environ.get('FIREBASE_PROJECT_ID'), \
"private_key_id": os.environ.get('PRIVATE_KEY_ID'), \
"private_key": os.environ.get('FIREBASE_PRIVATE_KEY').replace('\\n', '\n'), \
"client_email": os.environ.get('FIREBASE_CLIENT_EMAIL'), \
"client_id": os.environ.get('CLIENT_ID'), \
"auth_uri": os.environ.get('AUTH_URI'), \
"token_uri": os.environ.get('TOKEN_URI'), \
"auth_provider_x509_cert_url": os.environ.get('AUTH_PROVIDER_X509_CERT_URL'), \
"client_x509_cert_url": os.environ.get('CLIENT_X509_CERT_URL'), \
}),
})
Now, I'm getting this error:
ValueError: Illegal Firebase credential provided. App must be initialized with a valid credential instance.
I would ideally want to set up the application like this as I would prefer not to store the serviceAccount.json
on the cloud. Many of the examples I find are simply doing what I don't want to do.
What am I missing here?
Edit:
I am using the standard export <property_name>="..."
on my Mac OS terminal which I presume is the same as Linux environment. As a result, os.environ.get(<property_name>)
gets the corresponding value.
For reference:
I am trying to do the same thing as this:
https://www.benmvp.com/blog/initializing-firebase-admin-node-sdk-env-vars/
But with Python
Edit:
Looking at the source code here:
It appears that the exception is being thrown here. However, in my Flask API, I have the following:
cert = { \
"type": "service_account", \
"project_id": os.environ.get('FIREBASE_PROJECT_ID'), \
"private_key_id": os.environ.get('PRIVATE_KEY_ID'), \
"private_key": os.environ.get('FIREBASE_PRIVATE_KEY').replace('\\n', '\n'), \
"client_email": os.environ.get('FIREBASE_CLIENT_EMAIL'), \
"client_id": os.environ.get('CLIENT_ID'), \
"auth_uri": os.environ.get('AUTH_URI'), \
"token_uri": os.environ.get('TOKEN_URI'), \
"auth_provider_x509_cert_url": os.environ.get('AUTH_PROVIDER_X509_CERT_URL'), \
"client_x509_cert_url": os.environ.get('CLIENT_X509_CERT_URL'), \
print(type(credentials.Certificate(cert)), isinstance(credentials.Certificate(cert), credentials.Certificate), isinstance(credentials.Certificate(cert), credentials.Base))
To which the output is:
<class 'firebase_admin.credentials.Certificate'> True True
This doesn't make sense.. Since the following block:
if not isinstance(credential, credentials.Base):
Runs if isinstance(credential, credentials.Base)
is false. But I have the values as true.
Thanks to, smac89, for pointing me in the right direction.
The change is very minor to make it work:
firebase_admin.initialize_app({ \
credential=credentials.Certificate({ \ # <------- This change
"type": "service_account", \
"project_id": os.environ.get('FIREBASE_PROJECT_ID'), \
"private_key_id": os.environ.get('PRIVATE_KEY_ID'), \
"private_key": os.environ.get('FIREBASE_PRIVATE_KEY').replace('\\n', '\n'), \
"client_email": os.environ.get('FIREBASE_CLIENT_EMAIL'), \
"client_id": os.environ.get('CLIENT_ID'), \
"auth_uri": os.environ.get('AUTH_URI'), \
"token_uri": os.environ.get('TOKEN_URI'), \
"auth_provider_x509_cert_url": os.environ.get('AUTH_PROVIDER_X509_CERT_URL'), \
"client_x509_cert_url": os.environ.get('CLIENT_X509_CERT_URL'), \
}),
})
The method signature for initialize_app
is:
def initialize_app(credential=None, options=None, name=_DEFAULT_APP_NAME):
By not specifying the input to be credential
, the input was not read correctly. Guess I learnt something new about Python default values. :P