在不存储的情况下通过环境变量初始化 Firebase Admin serviceAccount.json

Initializing Firebase Admin via Environment Variables without storing serviceAccount.json

我正在尝试在我的 Flask API 上初始化 firebase-admin。根据文档,方法 initialize_app 可以将字典作为输入,如下所示:

https://github.com/firebase/firebase-admin-python/blob/6d826fd15c87db62f7501f569b6e0a762d17a05e/firebase_admin/credentials.py#L85

也就是说,我的代码结构如下:

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'), \
    }), 
})

现在,我收到此错误:

ValueError: Illegal Firebase credential provided. App must be initialized with a valid credential instance.

理想情况下,我希望像这样设置应用程序,因为我不想将 serviceAccount.json 存储在云中。我发现的许多示例只是在做我不想做的事情。

我在这里错过了什么?

编辑:

我在 Mac OS 终端上使用标准 export <property_name>="...",我认为它与 Linux 环境相同。结果os.environ.get(<property_name>)得到对应的值

供参考:

我正在尝试做同样的事情:

https://www.benmvp.com/blog/initializing-firebase-admin-node-sdk-env-vars/

但是 Python

编辑:

在这里查看源代码:

https://github.com/firebase/firebase-admin-python/blob/6d826fd15c87db62f7501f569b6e0a762d17a05e/firebase_admin/__init__.py#L209

看来这里抛出了异常。但是,在我的 Flask API 中,我有以下内容:

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))

输出为:

<class 'firebase_admin.credentials.Certificate'> True True

这没有意义.. 因为以下块:

if not isinstance(credential, credentials.Base):

如果 isinstance(credential, credentials.Base) 为假则运行。但我的价值观是真实的。

感谢 smac89 为我指明了正确的方向。

要使其正常工作,更改非常小:

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'), \
    }), 
})

initialize_app 的方法签名是:

def initialize_app(credential=None, options=None, name=_DEFAULT_APP_NAME):

由于未将输入指定为 credential,因此未正确读取输入。我想我学到了一些关于 Python 默认值的新知识。 :P