diff --git a/firebase_admin/auth.py b/firebase_admin/auth.py index e42dd4980..f6fb1da43 100644 --- a/firebase_admin/auth.py +++ b/firebase_admin/auth.py @@ -36,6 +36,7 @@ __all__ = [ 'ActionCodeSettings', 'CertificateFetchError', + 'Client', 'DELETE_ATTRIBUTE', 'EmailAlreadyExistsError', 'ErrorInfo', @@ -110,23 +111,23 @@ UserRecord = _user_mgt.UserRecord -def _get_auth_service(app): - """Returns an _AuthService instance for an App. +def _get_client(app): + """Returns a Client instance for an App. - If the App already has an _AuthService associated with it, simply returns - it. Otherwise creates a new _AuthService, and adds it to the App before + If the App already has a Client associated with it, simply returns + it. Otherwise creates a new Client, and adds it to the App before returning it. Args: app: A Firebase App instance (or None to use the default App). Returns: - _AuthService: An _AuthService for the specified App instance. + Client: A Client for the specified App instance. Raises: ValueError: If the app argument is invalid. """ - return _utils.get_app_service(app, _AUTH_ATTRIBUTE, _AuthService) + return _utils.get_app_service(app, _AUTH_ATTRIBUTE, Client) def create_custom_token(uid, developer_claims=None, app=None): @@ -145,8 +146,8 @@ def create_custom_token(uid, developer_claims=None, app=None): ValueError: If input parameters are invalid. TokenSignError: If an error occurs while signing the token using the remote IAM service. """ - service = _get_auth_service(app) - return service.create_custom_token(uid, developer_claims) + client = _get_client(app) + return client.create_custom_token(uid, developer_claims) def verify_id_token(id_token, app=None, check_revoked=False): @@ -171,8 +172,8 @@ def verify_id_token(id_token, app=None, check_revoked=False): CertificateFetchError: If an error occurs while fetching the public key certificates required to verify the ID token. """ - service = _get_auth_service(app) - return service.verify_id_token(id_token, check_revoked=check_revoked) + client = _get_client(app) + return client.verify_id_token(id_token, check_revoked=check_revoked) def create_session_cookie(id_token, expires_in, app=None): @@ -193,9 +194,9 @@ def create_session_cookie(id_token, expires_in, app=None): ValueError: If input parameters are invalid. FirebaseError: If an error occurs while creating the cookie. """ - service = _get_auth_service(app) + client = _get_client(app) # pylint: disable=protected-access - return service._token_generator.create_session_cookie(id_token, expires_in) + return client._token_generator.create_session_cookie(id_token, expires_in) def verify_session_cookie(session_cookie, check_revoked=False, app=None): @@ -220,11 +221,11 @@ def verify_session_cookie(session_cookie, check_revoked=False, app=None): CertificateFetchError: If an error occurs while fetching the public key certificates required to verify the session cookie. """ - service = _get_auth_service(app) + client = _get_client(app) # pylint: disable=protected-access - verified_claims = service._token_verifier.verify_session_cookie(session_cookie) + verified_claims = client._token_verifier.verify_session_cookie(session_cookie) if check_revoked: - service._check_jwt_revoked(verified_claims, RevokedSessionCookieError, 'session cookie') + client._check_jwt_revoked(verified_claims, RevokedSessionCookieError, 'session cookie') return verified_claims @@ -239,9 +240,17 @@ def revoke_refresh_tokens(uid, app=None): existing sessions from getting minted, existing ID tokens may remain active until their natural expiration (one hour). To verify that ID tokens are revoked, use ``verify_id_token(idToken, check_revoked=True)``. + + Args: + uid: A user ID string. + app: An App instance (optional). + + Raises: + ValueError: If the user ID is None, empty or malformed. + FirebaseError: If an error occurs while revoking the refresh token. """ - service = _get_auth_service(app) - service.revoke_refresh_tokens(uid) + client = _get_client(app) + client.revoke_refresh_tokens(uid) def get_user(uid, app=None): @@ -259,8 +268,8 @@ def get_user(uid, app=None): UserNotFoundError: If the specified user ID does not exist. FirebaseError: If an error occurs while retrieving the user. """ - service = _get_auth_service(app) - return service.get_user(uid=uid) + client = _get_client(app) + return client.get_user(uid=uid) def get_user_by_email(email, app=None): @@ -278,8 +287,8 @@ def get_user_by_email(email, app=None): UserNotFoundError: If no user exists by the specified email address. FirebaseError: If an error occurs while retrieving the user. """ - service = _get_auth_service(app) - return service.get_user_by_email(email=email) + client = _get_client(app) + return client.get_user_by_email(email=email) def get_user_by_phone_number(phone_number, app=None): @@ -297,8 +306,8 @@ def get_user_by_phone_number(phone_number, app=None): UserNotFoundError: If no user exists by the specified phone number. FirebaseError: If an error occurs while retrieving the user. """ - service = _get_auth_service(app) - return service.get_user_by_phone_number(phone_number=phone_number) + client = _get_client(app) + return client.get_user_by_phone_number(phone_number=phone_number) def list_users(page_token=None, max_results=_user_mgt.MAX_LIST_USERS_RESULTS, app=None): @@ -323,8 +332,8 @@ def list_users(page_token=None, max_results=_user_mgt.MAX_LIST_USERS_RESULTS, ap ValueError: If max_results or page_token are invalid. FirebaseError: If an error occurs while retrieving the user accounts. """ - service = _get_auth_service(app) - return service.list_users(page_token=page_token, max_results=max_results) + client = _get_client(app) + return client.list_users(page_token=page_token, max_results=max_results) def create_user(**kwargs): # pylint: disable=differing-param-doc @@ -353,8 +362,8 @@ def create_user(**kwargs): # pylint: disable=differing-param-doc FirebaseError: If an error occurs while creating the user account. """ app = kwargs.pop('app', None) - service = _get_auth_service(app) - return service.create_user(**kwargs) + client = _get_client(app) + return client.create_user(**kwargs) def update_user(uid, **kwargs): # pylint: disable=differing-param-doc @@ -378,8 +387,9 @@ def update_user(uid, **kwargs): # pylint: disable=differing-param-doc disabled: A boolean indicating whether or not the user account is disabled (optional). custom_claims: A dictionary or a JSON string contining the custom claims to be set on the user account (optional). To remove all custom claims, pass ``auth.DELETE_ATTRIBUTE``. - valid_since: An integer signifying the seconds since the epoch. This field is set by - ``revoke_refresh_tokens`` and it is discouraged to set this field directly. + valid_since: An integer signifying the seconds since the epoch (optional). This field is + set by ``revoke_refresh_tokens`` and it is discouraged to set this field directly. + app: An App instance (optional). Returns: UserRecord: An updated UserRecord instance for the user. @@ -389,8 +399,8 @@ def update_user(uid, **kwargs): # pylint: disable=differing-param-doc FirebaseError: If an error occurs while updating the user account. """ app = kwargs.pop('app', None) - service = _get_auth_service(app) - return service.update_user(uid, **kwargs) + client = _get_client(app) + return client.update_user(uid, **kwargs) def set_custom_user_claims(uid, custom_claims, app=None): @@ -413,8 +423,8 @@ def set_custom_user_claims(uid, custom_claims, app=None): ValueError: If the specified user ID or the custom claims are invalid. FirebaseError: If an error occurs while updating the user account. """ - service = _get_auth_service(app) - service.set_custom_user_claims(uid, custom_claims=custom_claims) + client = _get_client(app) + client.set_custom_user_claims(uid, custom_claims=custom_claims) def delete_user(uid, app=None): @@ -428,8 +438,8 @@ def delete_user(uid, app=None): ValueError: If the user ID is None, empty or malformed. FirebaseError: If an error occurs while deleting the user account. """ - service = _get_auth_service(app) - service.delete_user(uid) + client = _get_client(app) + client.delete_user(uid) def import_users(users, hash_alg=None, app=None): @@ -454,8 +464,8 @@ def import_users(users, hash_alg=None, app=None): ValueError: If the provided arguments are invalid. FirebaseError: If an error occurs while importing users. """ - service = _get_auth_service(app) - return service.import_users(users, hash_alg) + client = _get_client(app) + return client.import_users(users, hash_alg) def generate_password_reset_link(email, action_code_settings=None, app=None): @@ -475,8 +485,8 @@ def generate_password_reset_link(email, action_code_settings=None, app=None): ValueError: If the provided arguments are invalid FirebaseError: If an error occurs while generating the link """ - service = _get_auth_service(app) - return service.generate_password_reset_link(email, action_code_settings=action_code_settings) + client = _get_client(app) + return client.generate_password_reset_link(email, action_code_settings=action_code_settings) def generate_email_verification_link(email, action_code_settings=None, app=None): @@ -496,8 +506,8 @@ def generate_email_verification_link(email, action_code_settings=None, app=None) ValueError: If the provided arguments are invalid FirebaseError: If an error occurs while generating the link """ - service = _get_auth_service(app) - return service.generate_email_verification_link( + client = _get_client(app) + return client.generate_email_verification_link( email, action_code_settings=action_code_settings) @@ -518,14 +528,13 @@ def generate_sign_in_with_email_link(email, action_code_settings, app=None): ValueError: If the provided arguments are invalid FirebaseError: If an error occurs while generating the link """ - service = _get_auth_service(app) - return service.generate_sign_in_with_email_link( + client = _get_client(app) + return client.generate_sign_in_with_email_link( email, action_code_settings=action_code_settings) -# TODO: Rename to public type Client -class _AuthService: - """Firebase Authentication service.""" +class Client: + """Firebase Authentication client scoped to a specific tenant.""" ID_TOOLKIT_URL = 'https://identitytoolkit.googleapis.com/v1/projects/' @@ -553,14 +562,51 @@ def __init__(self, app, tenant_id=None): @property def tenant_id(self): + """Tenant ID associated with this client.""" return self._tenant_id def create_custom_token(self, uid, developer_claims=None): + """Builds and signs a Firebase custom auth token. + + Args: + uid: ID of the user for whom the token is created. + developer_claims: A dictionary of claims to be included in the token + (optional). + + Returns: + bytes: A token minted from the input parameters. + + Raises: + ValueError: If input parameters are invalid. + TokenSignError: If an error occurs while signing the token using the remote IAM service. + """ return self._token_generator.create_custom_token( uid, developer_claims, tenant_id=self.tenant_id) def verify_id_token(self, id_token, check_revoked=False): - """Verifies the signature and data for the provided ID token.""" + """Verifies the signature and data for the provided JWT. + + Accepts a signed token string, verifies that it is current, and issued + to this project, and that it was correctly signed by Google. + + Args: + id_token: A string of the encoded JWT. + check_revoked: Boolean, If true, checks whether the token has been revoked (optional). + + Returns: + dict: A dictionary of key-value pairs parsed from the decoded JWT. + + Raises: + ValueError: If ``id_token`` is a not a string or is empty. + InvalidIdTokenError: If ``id_token`` is not a valid Firebase ID token. + ExpiredIdTokenError: If the specified ID token has expired. + RevokedIdTokenError: If ``check_revoked`` is ``True`` and the ID token has been + revoked. + TenantIdMismatchError: If ``id_token`` belongs to a tenant that is different than + this ``Client`` instance. + CertificateFetchError: If an error occurs while fetching the public key certificates + required to verify the ID token. + """ if not isinstance(check_revoked, bool): # guard against accidental wrong assignment. raise ValueError('Illegal check_revoked argument. Argument must be of type ' @@ -578,54 +624,282 @@ def verify_id_token(self, id_token, check_revoked=False): return verified_claims def revoke_refresh_tokens(self, uid): + """Revokes all refresh tokens for an existing user. + + revoke_refresh_tokens updates the user's tokens_valid_after_timestamp to the current UTC + in seconds since the epoch. It is important that the server on which this is called has its + clock set correctly and synchronized. + + While this revokes all sessions for a specified user and disables any new ID tokens for + existing sessions from getting minted, existing ID tokens may remain active until their + natural expiration (one hour). To verify that ID tokens are revoked, use + ``verify_id_token(idToken, check_revoked=True)``. + + Args: + uid: A user ID string. + + Raises: + ValueError: If the user ID is None, empty or malformed. + FirebaseError: If an error occurs while revoking the refresh token. + """ self._user_manager.update_user(uid, valid_since=int(time.time())) def get_user(self, uid): + """Gets the user data corresponding to the specified user ID. + + Args: + uid: A user ID string. + + Returns: + UserRecord: A UserRecord instance. + + Raises: + ValueError: If the user ID is None, empty or malformed. + UserNotFoundError: If the specified user ID does not exist. + FirebaseError: If an error occurs while retrieving the user. + """ response = self._user_manager.get_user(uid=uid) return UserRecord(response) def get_user_by_email(self, email): + """Gets the user data corresponding to the specified user email. + + Args: + email: A user email address string. + + Returns: + UserRecord: A UserRecord instance. + + Raises: + ValueError: If the email is None, empty or malformed. + UserNotFoundError: If no user exists by the specified email address. + FirebaseError: If an error occurs while retrieving the user. + """ response = self._user_manager.get_user(email=email) return UserRecord(response) def get_user_by_phone_number(self, phone_number): + """Gets the user data corresponding to the specified phone number. + + Args: + phone_number: A phone number string. + + Returns: + UserRecord: A UserRecord instance. + + Raises: + ValueError: If the phone number is None, empty or malformed. + UserNotFoundError: If no user exists by the specified phone number. + FirebaseError: If an error occurs while retrieving the user. + """ response = self._user_manager.get_user(phone_number=phone_number) return UserRecord(response) def list_users(self, page_token=None, max_results=_user_mgt.MAX_LIST_USERS_RESULTS): + """Retrieves a page of user accounts from a Firebase project. + + The ``page_token`` argument governs the starting point of the page. The ``max_results`` + argument governs the maximum number of user accounts that may be included in the returned + page. This function never returns None. If there are no user accounts in the Firebase + project, this returns an empty page. + + Args: + page_token: A non-empty page token string, which indicates the starting point of the + page (optional). Defaults to ``None``, which will retrieve the first page of users. + max_results: A positive integer indicating the maximum number of users to include in + the returned page (optional). Defaults to 1000, which is also the maximum number + allowed. + + Returns: + ListUsersPage: A ListUsersPage instance. + + Raises: + ValueError: If max_results or page_token are invalid. + FirebaseError: If an error occurs while retrieving the user accounts. + """ def download(page_token, max_results): return self._user_manager.list_users(page_token, max_results) return ListUsersPage(download, page_token, max_results) - def create_user(self, **kwargs): + def create_user(self, **kwargs): # pylint: disable=differing-param-doc + """Creates a new user account with the specified properties. + + Args: + kwargs: A series of keyword arguments (optional). + + Keyword Args: + uid: User ID to assign to the newly created user (optional). + display_name: The user's display name (optional). + email: The user's primary email (optional). + email_verified: A boolean indicating whether or not the user's primary email is + verified (optional). + phone_number: The user's primary phone number (optional). + photo_url: The user's photo URL (optional). + password: The user's raw, unhashed password. (optional). + disabled: A boolean indicating whether or not the user account is disabled (optional). + + Returns: + UserRecord: A UserRecord instance for the newly created user. + + Raises: + ValueError: If the specified user properties are invalid. + FirebaseError: If an error occurs while creating the user account. + """ uid = self._user_manager.create_user(**kwargs) return self.get_user(uid=uid) - def update_user(self, uid, **kwargs): + def update_user(self, uid, **kwargs): # pylint: disable=differing-param-doc + """Updates an existing user account with the specified properties. + + Args: + uid: A user ID string. + kwargs: A series of keyword arguments (optional). + + Keyword Args: + display_name: The user's display name (optional). Can be removed by explicitly passing + ``auth.DELETE_ATTRIBUTE``. + email: The user's primary email (optional). + email_verified: A boolean indicating whether or not the user's primary email is + verified (optional). + phone_number: The user's primary phone number (optional). Can be removed by explicitly + passing ``auth.DELETE_ATTRIBUTE``. + photo_url: The user's photo URL (optional). Can be removed by explicitly passing + ``auth.DELETE_ATTRIBUTE``. + password: The user's raw, unhashed password. (optional). + disabled: A boolean indicating whether or not the user account is disabled (optional). + custom_claims: A dictionary or a JSON string contining the custom claims to be set on + the user account (optional). To remove all custom claims, pass + ``auth.DELETE_ATTRIBUTE``. + valid_since: An integer signifying the seconds since the epoch (optional). This field + is set by ``revoke_refresh_tokens`` and it is discouraged to set this field + directly. + + Returns: + UserRecord: An updated UserRecord instance for the user. + + Raises: + ValueError: If the specified user ID or properties are invalid. + FirebaseError: If an error occurs while updating the user account. + """ self._user_manager.update_user(uid, **kwargs) return self.get_user(uid=uid) def set_custom_user_claims(self, uid, custom_claims): + """Sets additional claims on an existing user account. + + Custom claims set via this function can be used to define user roles and privilege levels. + These claims propagate to all the devices where the user is already signed in (after token + expiration or when token refresh is forced), and next time the user signs in. The claims + can be accessed via the user's ID token JWT. If a reserved OIDC claim is specified (sub, + iat, iss, etc), an error is thrown. Claims payload must also not be larger then 1000 + characters when serialized into a JSON string. + + Args: + uid: A user ID string. + custom_claims: A dictionary or a JSON string of custom claims. Pass None to unset any + claims set previously. + + Raises: + ValueError: If the specified user ID or the custom claims are invalid. + FirebaseError: If an error occurs while updating the user account. + """ if custom_claims is None: custom_claims = DELETE_ATTRIBUTE self._user_manager.update_user(uid, custom_claims=custom_claims) def delete_user(self, uid): + """Deletes the user identified by the specified user ID. + + Args: + uid: A user ID string. + + Raises: + ValueError: If the user ID is None, empty or malformed. + FirebaseError: If an error occurs while deleting the user account. + """ self._user_manager.delete_user(uid) def import_users(self, users, hash_alg=None): + """Imports the specified list of users into Firebase Auth. + + At most 1000 users can be imported at a time. This operation is optimized for bulk imports + and will ignore checks on identifier uniqueness which could result in duplications. The + ``hash_alg`` parameter must be specified when importing users with passwords. Refer to the + ``UserImportHash`` class for supported hash algorithms. + + Args: + users: A list of ``ImportUserRecord`` instances to import. Length of the list must not + exceed 1000. + hash_alg: A ``UserImportHash`` object (optional). Required when importing users with + passwords. + + Returns: + UserImportResult: An object summarizing the result of the import operation. + + Raises: + ValueError: If the provided arguments are invalid. + FirebaseError: If an error occurs while importing users. + """ result = self._user_manager.import_users(users, hash_alg) return UserImportResult(result, len(users)) def generate_password_reset_link(self, email, action_code_settings=None): + """Generates the out-of-band email action link for password reset flows for the specified + email address. + + Args: + email: The email of the user whose password is to be reset. + action_code_settings: ``ActionCodeSettings`` instance (optional). Defines whether + the link is to be handled by a mobile app and the additional state information to + be passed in the deep link. + + Returns: + link: The password reset link created by the API + + Raises: + ValueError: If the provided arguments are invalid + FirebaseError: If an error occurs while generating the link + """ return self._user_manager.generate_email_action_link( 'PASSWORD_RESET', email, action_code_settings=action_code_settings) def generate_email_verification_link(self, email, action_code_settings=None): + """Generates the out-of-band email action link for email verification flows for the + specified email address. + + Args: + email: The email of the user to be verified. + action_code_settings: ``ActionCodeSettings`` instance (optional). Defines whether + the link is to be handled by a mobile app and the additional state information to + be passed in the deep link. + + Returns: + link: The email verification link created by the API + + Raises: + ValueError: If the provided arguments are invalid + FirebaseError: If an error occurs while generating the link + """ return self._user_manager.generate_email_action_link( 'VERIFY_EMAIL', email, action_code_settings=action_code_settings) def generate_sign_in_with_email_link(self, email, action_code_settings): + """Generates the out-of-band email action link for email link sign-in flows, using the + action code settings provided. + + Args: + email: The email of the user signing in. + action_code_settings: ``ActionCodeSettings`` instance. Defines whether + the link is to be handled by a mobile app and the additional state information to be + passed in the deep link. + + Returns: + link: The email sign-in link created by the API + + Raises: + ValueError: If the provided arguments are invalid + FirebaseError: If an error occurs while generating the link + """ return self._user_manager.generate_email_action_link( 'EMAIL_SIGNIN', email, action_code_settings=action_code_settings) diff --git a/firebase_admin/tenant_mgt.py b/firebase_admin/tenant_mgt.py index 2139be018..1fb64d01c 100644 --- a/firebase_admin/tenant_mgt.py +++ b/firebase_admin/tenant_mgt.py @@ -60,7 +60,7 @@ def auth_for_tenant(tenant_id, app=None): app: An App instance (optional). Returns: - _AuthService: An _AuthService object. + auth.Client: An ``auth.Client`` object. Raises: ValueError: If the tenant ID is None, empty or not a string. @@ -251,7 +251,7 @@ def auth_for_tenant(self, tenant_id): if tenant_id in self.tenant_clients: return self.tenant_clients[tenant_id] - client = auth._AuthService(self.app, tenant_id=tenant_id) # pylint: disable=protected-access + client = auth.Client(self.app, tenant_id=tenant_id) self.tenant_clients[tenant_id] = client return client diff --git a/tests/test_tenant_mgt.py b/tests/test_tenant_mgt.py index da14c954f..47a647129 100644 --- a/tests/test_tenant_mgt.py +++ b/tests/test_tenant_mgt.py @@ -104,7 +104,7 @@ def _instrument_user_mgt(client, status, payload): recorder = [] user_manager = client._user_manager user_manager._client.session.mount( - auth._AuthService.ID_TOOLKIT_URL, + auth.Client.ID_TOOLKIT_URL, testutils.MockAdapter(payload, status, recorder)) return recorder diff --git a/tests/test_token_gen.py b/tests/test_token_gen.py index 072de3f16..dbb7020cf 100644 --- a/tests/test_token_gen.py +++ b/tests/test_token_gen.py @@ -117,21 +117,21 @@ def _get_session_cookie(payload_overrides=None, header_overrides=None): return _get_id_token(payload_overrides, header_overrides) def _instrument_user_manager(app, status, payload): - auth_service = auth._get_auth_service(app) - user_manager = auth_service._user_manager + client = auth._get_client(app) + user_manager = client._user_manager recorder = [] user_manager._client.session.mount( - auth._AuthService.ID_TOOLKIT_URL, + auth.Client.ID_TOOLKIT_URL, testutils.MockAdapter(payload, status, recorder)) return user_manager, recorder def _overwrite_cert_request(app, request): - auth_service = auth._get_auth_service(app) - auth_service._token_verifier.request = request + client = auth._get_client(app) + client._token_verifier.request = request def _overwrite_iam_request(app, request): - auth_service = auth._get_auth_service(app) - auth_service._token_generator.request = request + client = auth._get_client(app) + client._token_generator.request = request @pytest.fixture(scope='module') def auth_app(): @@ -253,8 +253,9 @@ def test_sign_with_discovered_service_account(self): try: _overwrite_iam_request(app, request) # Force initialization of the signing provider. This will invoke the Metadata service. - auth_service = auth._get_auth_service(app) - assert auth_service._token_generator.signing_provider is not None + client = auth._get_client(app) + assert client._token_generator.signing_provider is not None + # Now invoke the IAM signer. signature = base64.b64encode(b'test').decode() request.response = testutils.MockResponse( diff --git a/tests/test_user_mgt.py b/tests/test_user_mgt.py index 42d436e4d..4f4efbd28 100644 --- a/tests/test_user_mgt.py +++ b/tests/test_user_mgt.py @@ -58,11 +58,11 @@ def user_mgt_app(): firebase_admin.delete_app(app) def _instrument_user_manager(app, status, payload): - auth_service = auth._get_auth_service(app) - user_manager = auth_service._user_manager + client = auth._get_client(app) + user_manager = client._user_manager recorder = [] user_manager._client.session.mount( - auth._AuthService.ID_TOOLKIT_URL, + auth.Client.ID_TOOLKIT_URL, testutils.MockAdapter(payload, status, recorder)) return user_manager, recorder @@ -104,14 +104,14 @@ def _check_user_record(user, expected_uid='testuser'): class TestAuthServiceInitialization: def test_default_timeout(self, user_mgt_app): - auth_service = auth._get_auth_service(user_mgt_app) - user_manager = auth_service._user_manager + client = auth._get_client(user_mgt_app) + user_manager = client._user_manager assert user_manager._client.timeout == _http_client.DEFAULT_TIMEOUT_SECONDS def test_fail_on_no_project_id(self): app = firebase_admin.initialize_app(testutils.MockCredential(), name='userMgt2') with pytest.raises(ValueError): - auth._get_auth_service(app) + auth._get_client(app) firebase_admin.delete_app(app) @@ -1301,7 +1301,7 @@ def test_bad_settings_data(self, user_mgt_app, func): def test_bad_action_type(self, user_mgt_app): with pytest.raises(ValueError): - auth._get_auth_service(user_mgt_app) \ + auth._get_client(user_mgt_app) \ ._user_manager \ .generate_email_action_link('BAD_TYPE', 'test@test.com', action_code_settings=MOCK_ACTION_CODE_SETTINGS)