|  | 
| 18 | 18 | Google Cloud Identity Platform (GCIP) instance. | 
| 19 | 19 | """ | 
| 20 | 20 | 
 | 
|  | 21 | +import threading | 
|  | 22 | + | 
| 21 | 23 | import requests | 
| 22 | 24 | 
 | 
| 23 | 25 | import firebase_admin | 
|  | 26 | +from firebase_admin import auth | 
| 24 | 27 | from firebase_admin import _auth_utils | 
| 25 | 28 | from firebase_admin import _http_client | 
| 26 | 29 | from firebase_admin import _utils | 
|  | 
| 35 | 38 |     'Tenant', | 
| 36 | 39 |     'TenantNotFoundError', | 
| 37 | 40 | 
 | 
|  | 41 | +    'auth_for_tenant', | 
| 38 | 42 |     'create_tenant', | 
| 39 | 43 |     'delete_tenant', | 
| 40 | 44 |     'get_tenant', | 
|  | 
| 45 | 49 | TenantNotFoundError = _auth_utils.TenantNotFoundError | 
| 46 | 50 | 
 | 
| 47 | 51 | 
 | 
|  | 52 | +def auth_for_tenant(tenant_id, app=None): | 
|  | 53 | +    """Gets an Auth Client instance scoped to the given tenant ID. | 
|  | 54 | +
 | 
|  | 55 | +    Args: | 
|  | 56 | +        tenant_id: A tenant ID string. | 
|  | 57 | +        app: An App instance (optional). | 
|  | 58 | +
 | 
|  | 59 | +    Returns: | 
|  | 60 | +        _AuthService: An _AuthService object. | 
|  | 61 | +
 | 
|  | 62 | +    Raises: | 
|  | 63 | +        ValueError: If the tenant ID is None, empty or not a string. | 
|  | 64 | +    """ | 
|  | 65 | +    tenant_mgt_service = _get_tenant_mgt_service(app) | 
|  | 66 | +    return tenant_mgt_service.auth_for_tenant(tenant_id) | 
|  | 67 | + | 
|  | 68 | + | 
| 48 | 69 | def get_tenant(tenant_id, app=None): | 
| 49 | 70 |     """Gets the tenant corresponding to the given ``tenant_id``. | 
| 50 | 71 | 
 | 
| @@ -211,8 +232,25 @@ def __init__(self, app): | 
| 211 | 232 |         credential = app.credential.get_credential() | 
| 212 | 233 |         version_header = 'Python/Admin/{0}'.format(firebase_admin.__version__) | 
| 213 | 234 |         base_url = '{0}/projects/{1}'.format(self.TENANT_MGT_URL, app.project_id) | 
|  | 235 | +        self.app = app | 
| 214 | 236 |         self.client = _http_client.JsonHttpClient( | 
| 215 | 237 |             credential=credential, base_url=base_url, headers={'X-Client-Version': version_header}) | 
|  | 238 | +        self.tenant_clients = {} | 
|  | 239 | +        self.lock = threading.RLock() | 
|  | 240 | + | 
|  | 241 | +    def auth_for_tenant(self, tenant_id): | 
|  | 242 | +        """Gets an Auth Client instance scoped to the given tenant ID.""" | 
|  | 243 | +        if not isinstance(tenant_id, str) or not tenant_id: | 
|  | 244 | +            raise ValueError( | 
|  | 245 | +                'Invalid tenant ID: {0}. Tenant ID must be a non-empty string.'.format(tenant_id)) | 
|  | 246 | + | 
|  | 247 | +        with self.lock: | 
|  | 248 | +            if tenant_id in self.tenant_clients: | 
|  | 249 | +                return self.tenant_clients[tenant_id] | 
|  | 250 | + | 
|  | 251 | +            client = auth._AuthService(self.app, tenant_id=tenant_id) # pylint: disable=protected-access | 
|  | 252 | +            self.tenant_clients[tenant_id] = client | 
|  | 253 | +            return  client | 
| 216 | 254 | 
 | 
| 217 | 255 |     def get_tenant(self, tenant_id): | 
| 218 | 256 |         """Gets the tenant corresponding to the given ``tenant_id``.""" | 
|  | 
0 commit comments