【问题标题】:How to use an emulator for each instance of firebase_admin app, in the same project如何在同一个项目中为 firebase_admin 应用程序的每个实例使用模拟器
【发布时间】:2021-11-24 12:41:18
【问题描述】:

我正在尝试做的是将模拟器连接到 firebase_admin 的一个实例以进行管理员身份验证,并在同一个 api 中将另一个实例连接到 Web 身份验证。

问题是我无法为每个 firebase_admin 实例设置每个模拟器的主机。发生的情况是它总是采用它在模块的最后一个实例中声明的环境变量。从下面的python脚本中可以看出。

#!/usr/bin/env python3
"""
src.firebase.py

Initialize firebase_admin for admin & web
"""

import os
from firebase_admin import initialize_app 
from firebase_admin import credentials     
from firebase_admin import auth

def initialize_admin():
    os.environ["FIREBASE_AUTH_EMULATOR_HOST"] = os.getenv("FIREBASE_AUTH_EMULATOR_ADMIN_HOST")
    sdk_cred = credentials.Certificate(
        os.path.abspath(
            os.path.join(__package__, "./config/conexperto-admin-sdk.json")
        )
    )
    return initialize_app(
        credential=sdk_cred, name="admin"
    )
    
def initialize_web():
    os.environ["FIREBASE_AUTH_EMULATOR_HOST"] = os.getenv("FIREBASE_AUTH_EMULATOR_WEB_HOST")
    sdk_cred = credentials.Certificate(
        os.path.abspath(
            os.path.join(__package__, "./config/conexperto-web-sdk.json")
        )
    )
    return initialize_app(
        credential=sdk_cred, name="web"
    )
    
admin_sdk = initialize_admin()
web_sdk = initialize_web()

user_admin = auth.get_user(uid, app=admin_sdk) # in this instance admin_sdk is linked to the emulator web, what causes the error 
web_admin = auth.get_user(uid, app=web_sdk)

因此,在创建管理员用户时,会使用 admin_sdk 的凭据对其进行签名并保存在 Web 模拟器中。当使用所述用户登录并验证令牌时,它会抛出签名错误'aud'。

我正在使用的 firebase_admin 版本

firebase_admin-5.0.1

【问题讨论】:

    标签: python firebase api firebase-authentication firebase-admin


    【解决方案1】:

    通过阅读 firebase_admin 源代码并进行一些逆向工程,我找到了自己问题的解决方案。

    函数 initialize_app 它在分析和准备 sdk 凭据时所做的工作,以供以后由每个服务的客户端使用,无论是 auth 还是 firestore 等。每个服务的客户端都是请求构造函数,服务本身就是一个客户端的抽象。

    因此,在获取身份验证服务的客户端auth._get_client (sdk_app)时,会调用其构造函数并声明url,同时考虑环境变量FIREBASE_AUTH_EMULATOR_HOST

    #!/usr/bin/env python3
    """
    src.firebase.py
    
    Initialize firebase_admin for admin & web
    """
    import os
    
    from firebase_admin import auth
    from firebase_admin import credentials
    from firebase_admin import initialize_app
    
    
    class sdk:
        def __init__(self, sdk, auth):
            self.sdk = sdk
            self.auth = auth
    
    
    def initialize_admin():
        os.environ["FIREBASE_AUTH_EMULATOR_HOST"] = os.getenv(
            "FIREBASE_AUTH_EMULATOR_ADMIN_HOST"
        )
        sdk_cred = credentials.Certificate(
            os.path.abspath(
                os.path.join(__package__, "./config/conexperto-admin-sdk.json")
            )
        )
        sdk_app = initialize_app(credential=sdk_cred, name="admin")
        client = auth._get_client(sdk_app)
        return sdk(sdk_app, client)
    
    
    def initialize_web():
        os.environ["FIREBASE_AUTH_EMULATOR_HOST"] = os.getenv(
            "FIREBASE_AUTH_EMULATOR_WEB_HOST"
        )
        sdk_cred = credentials.Certificate(
            os.path.abspath(
                os.path.join(__package__, "./config/conexperto-web-sdk.json")
            )
        )
        sdk_app = initialize_app(credential=sdk_cred, name="web")
        client = auth._get_client(sdk_app)
        return sdk(sdk_app, client)
    
    
    admin_sdk = initialize_admin()
    web_sdk = initialize_web()
    

    要使用这个客户端,我们如下进行。

    admin_sdk.auth.get_user(uid)
    web_sdk.auth.get_user(uid)
    
    admin_sdk.auth.create_user(**kwargs)
    web_sdk.auth.create_user(**kwargs)
    # And so for each of the auth service methods 
    

    这个解决方案我只在firebase_admin-5.0.1 for python3 中测试过。

    【讨论】:

      猜你喜欢
      • 2019-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多