1414
1515"""Firebase auth client sub module."""
1616
17+ import os
1718import time
1819
20+ from google .oauth2 import credentials
21+ from google .auth .exceptions import DefaultCredentialsError
22+
1923import firebase_admin
2024from firebase_admin import _auth_providers
2125from firebase_admin import _auth_utils
2529from firebase_admin import _user_import
2630from firebase_admin import _user_mgt
2731
32+ _EMULATOR_HOST_ENV_VAR = 'FIREBASE_AUTH_EMULATOR_HOST'
33+ _DEFAULT_AUTH_URL = 'https://identitytoolkit.googleapis.com'
2834
2935class Client :
3036 """Firebase Authentication client scoped to a specific tenant."""
@@ -36,17 +42,45 @@ def __init__(self, app, tenant_id=None):
3642 2. set the project ID explicitly via Firebase App options, or
3743 3. set the project ID via the GOOGLE_CLOUD_PROJECT environment variable.""" )
3844
39- credential = app . credential . get_credential ()
45+ credential = None
4046 version_header = 'Python/Admin/{0}' .format (firebase_admin .__version__ )
47+ # Non-default endpoint URLs for emulator support are set in this dict later.
48+ id_toolkit_endpoints = {}
49+
50+ # If an emulator is present, check that the given value matches the expected format and set
51+ # endpoint URLs to use the emulator. Also set a fake authorization token.
52+ emulator_host = os .environ .get (_EMULATOR_HOST_ENV_VAR )
53+ if emulator_host :
54+ if '//' in emulator_host :
55+ raise ValueError (
56+ 'Invalid {0}: "{1}". It must follow format "host:port".' .format (
57+ _EMULATOR_HOST_ENV_VAR , emulator_host ))
58+ base_url = 'http://{0}/identitytoolkit.googleapis.com' .format (emulator_host )
59+ id_toolkit_endpoints ['v1' ] = base_url + '/v1'
60+ id_toolkit_endpoints ['v2beta1' ] = base_url + '/v2beta1'
61+
62+ try :
63+ # Use credentials if provided
64+ credential = app .credential .get_credential ()
65+ except DefaultCredentialsError as credential_error :
66+ # The emulator can make do with fake credentials
67+ if emulator_host :
68+ credential = credentials .Credentials (token = 'owner' )
69+ else :
70+ # Not emulated, no credential, raise
71+ raise credential_error
72+
4173 http_client = _http_client .JsonHttpClient (
4274 credential = credential , headers = {'X-Client-Version' : version_header })
4375
4476 self ._tenant_id = tenant_id
45- self ._token_generator = _token_gen .TokenGenerator (app , http_client )
77+ self ._token_generator = _token_gen .TokenGenerator (
78+ app , http_client , id_toolkit_endpoints .get ('v1' ))
4679 self ._token_verifier = _token_gen .TokenVerifier (app )
47- self ._user_manager = _user_mgt .UserManager (http_client , app .project_id , tenant_id )
80+ self ._user_manager = _user_mgt .UserManager (
81+ http_client , app .project_id , tenant_id , id_toolkit_endpoints .get ('v1' ))
4882 self ._provider_manager = _auth_providers .ProviderConfigClient (
49- http_client , app .project_id , tenant_id )
83+ http_client , app .project_id , tenant_id , id_toolkit_endpoints . get ( 'v2beta1' ) )
5084
5185 @property
5286 def tenant_id (self ):
0 commit comments