0

What I'm trying to do is connect an emulator to an instance of firebase_admin for admin authentication and another instance for web authentication in the same api.

The problem is that i cannot set the host of each emulator for each instance of firebase_admin. What happens is that it always takes the environment variable that it declares in the last instance of the module. As can be seen in the following python script.

#!/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)

Therefore, when creating an admin user, it is signed with the credentials of admin_sdk and saved in the web emulator. That when logging in with said user and verifying the token, it will throw a signature error 'aud'.

firebase_admin version that I am using

firebase_admin-5.0.1
frfernandezdev
  • 383
  • 4
  • 10

1 Answers1

0

By reading the firebase_admin source code and doing a bit of reverse engineering, I found the solution to my own question.

The function initialize_app what it does in analyzing and preparing the sdk credentials, to later be used by the clients of each services, be it auth or firestore, etc. The clients of each services are request constructors and the service is itself an abstraction of the client.

Therefore, when obtaining the client auth._get_client (sdk_app) of the auth service, the constructor of the same is being called and it declares the url, taking into account the environment variable 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()

To use this client, we do it as follows.

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 

This solution I have only tested in firebase_admin-5.0.1 for python3.

frfernandezdev
  • 383
  • 4
  • 10