diff --git a/V4_MIGRATION_GUIDE.md b/V4_MIGRATION_GUIDE.md index b16a96df..74266853 100644 --- a/V4_MIGRATION_GUIDE.md +++ b/V4_MIGRATION_GUIDE.md @@ -2,13 +2,14 @@ Guide to migrating from `3.x` to `4.x` -- [Python <3.6 is no longer supported](#python-36-is-no-longer-supported) +- [Python <3.7 is no longer supported](#python-37-is-no-longer-supported) - [Client ID and client secret are now specified in the constructor for authentication clients](#client-id-and-client-secret-are-now-specified-in-the-constructor-for-authentication-clients) - [AuthorizeClient and Logout have been removed](#authorizeclient-and-logout-have-been-removed) +- [Methods that call deprecated endpoints have been removed](#methods-that-call-deprecated-endpoints-have-been-removed) -## Python <3.6 is no longer supported +## Python <3.7 is no longer supported -Python 3.5 and Python 2 are EOL and are no longer supported. +Python <=3.6 and Python 2 are EOL and are no longer supported. ## Client ID and client secret are now specified in the constructor for authentication clients @@ -35,4 +36,19 @@ get_token.client_credentials('my-api') ## AuthorizeClient and Logout have been removed -The authorize and logout requests need to be done in a user agent, so it didn't make sense to include them in a REST client. \ No newline at end of file +The authorize and logout requests need to be done in a user agent, so it didn't make sense to include them in a REST client. + +## Methods that call deprecated endpoints have been removed + +The following methods have been removed: + +### Authentication + +- `database.login` - Use `get_token.login` +- `passwordless.sms_login` - Use `get_token.passwordless_login` +- `users.tokeninfo` - `users.userinfo` + +### Management + +- `users.delete_all_users` - Use `users.delete` +- `jobs.get_results` - Use `jobs.get` \ No newline at end of file diff --git a/auth0/v3/authentication/database.py b/auth0/v3/authentication/database.py index 48f8ef41..fe8fd374 100644 --- a/auth0/v3/authentication/database.py +++ b/auth0/v3/authentication/database.py @@ -10,44 +10,6 @@ class Database(AuthenticationBase): domain (str): Your auth0 domain (e.g: username.auth0.com) """ - def login( - self, - username, - password, - connection, - id_token=None, - grant_type="password", - device=None, - scope="openid", - ): - """Login using username and password - - Given the user credentials and the connection specified, it will do - the authentication on the provider and return a dict with the - access_token and id_token. This endpoint only works for database - connections, passwordless connections, Active Directory/LDAP, - Windows Azure AD and ADFS. - """ - warnings.warn( - "/oauth/ro will be deprecated in future releases", DeprecationWarning - ) - - body = { - "client_id": self.client_id, - "username": username, - "password": password, - "connection": connection, - "grant_type": grant_type, - "scope": scope, - } - if id_token: - body.update({"id_token": id_token}) - if device: - body.update({"device": device}) - return self.post( - "{}://{}/oauth/ro".format(self.protocol, self.domain), data=body - ) - def signup( self, email, diff --git a/auth0/v3/authentication/passwordless.py b/auth0/v3/authentication/passwordless.py index ef8306d9..ee49f750 100644 --- a/auth0/v3/authentication/passwordless.py +++ b/auth0/v3/authentication/passwordless.py @@ -70,29 +70,3 @@ def sms(self, phone_number): return self.authenticated_post( "{}://{}/passwordless/start".format(self.protocol, self.domain), data=data ) - - def sms_login(self, phone_number, code, scope="openid"): - """Login using phone number/verification code. - - Args: - phone_number (str): Phone number. - - code (str): Code received in the SMS. - - scope (str, optional): Scope to use. Defaults to 'openid'. - """ - warnings.warn( - "/oauth/ro will be deprecated in future releases", DeprecationWarning - ) - - return self.post( - "{}://{}/oauth/ro".format(self.protocol, self.domain), - data={ - "client_id": self.client_id, - "connection": "sms", - "grant_type": "password", - "username": phone_number, - "password": code, - "scope": scope, - }, - ) diff --git a/auth0/v3/authentication/users.py b/auth0/v3/authentication/users.py index 5dd035ff..69a305d3 100644 --- a/auth0/v3/authentication/users.py +++ b/auth0/v3/authentication/users.py @@ -49,25 +49,3 @@ def userinfo(self, access_token): url="{}://{}/userinfo".format(self.protocol, self.domain), headers={"Authorization": "Bearer {}".format(access_token)}, ) - - def tokeninfo(self, jwt): - - """Returns user profile based on the user's jwt - - Validates a JSON Web Token (signature and expiration) and returns the - user information associated with the user id (sub property) of - the token. - - Args: - jwt (str): User's jwt - - Returns: - The user profile. - """ - warnings.warn( - "/tokeninfo will be deprecated in future releases", DeprecationWarning - ) - return self.client.post( - url="{}://{}/tokeninfo".format(self.protocol, self.domain), - data={"id_token": jwt}, - ) diff --git a/auth0/v3/management/jobs.py b/auth0/v3/management/jobs.py index 8f56aa72..69ed40ba 100644 --- a/auth0/v3/management/jobs.py +++ b/auth0/v3/management/jobs.py @@ -67,25 +67,6 @@ def get_failed_job(self, id): url = self._url("{}/errors".format(id)) return self.client.get(url) - def get_results(self, job_id): - """Get results of a job - - Args: - job_id (str): The id of the job. - - Deprecation: - The /jobs/{id}/results endpoint was removed from the Management API. - You can obtain the Job results by querying a Job by ID. - - See: https://auth0.com/docs/api/management/v2#!/Jobs/get_jobs_by_id - """ - warnings.warn( - "/jobs/{id}/results is no longer available. The get(id) function will be" - " called instead.", - DeprecationWarning, - ) - return self.get(job_id) - def export_users(self, body): """Export all users to a file using a long running job. diff --git a/auth0/v3/management/users.py b/auth0/v3/management/users.py index 74be1149..f625c49c 100644 --- a/auth0/v3/management/users.py +++ b/auth0/v3/management/users.py @@ -116,17 +116,6 @@ def create(self, body): """ return self.client.post(self._url(), data=body) - def delete_all_users(self): - """Deletes all users (USE WITH CAUTION). - Deprecation: This endpoint is no longer available server-side. - - Args: - """ - warnings.warn( - "DELETE all users endpoint is no longer available.", DeprecationWarning - ) - return self.client.delete(self._url()) - def get(self, id, fields=None, include_fields=True): """Get a user. diff --git a/auth0/v3/test/authentication/test_database.py b/auth0/v3/test/authentication/test_database.py index 920907f1..442ddb8e 100644 --- a/auth0/v3/test/authentication/test_database.py +++ b/auth0/v3/test/authentication/test_database.py @@ -6,37 +6,6 @@ class TestDatabase(unittest.TestCase): - @mock.patch("auth0.v3.rest.RestClient.post") - def test_login(self, mock_post): - d = Database("my.domain.com", "cid") - - d.login( - username="usrnm", - password="pswd", - id_token="idt", - connection="conn", - device="dev", - grant_type="gt", - scope="openid profile", - ) - - args, kwargs = mock_post.call_args - - self.assertEqual(args[0], "https://my.domain.com/oauth/ro") - self.assertEqual( - kwargs["data"], - { - "client_id": "cid", - "username": "usrnm", - "password": "pswd", - "id_token": "idt", - "connection": "conn", - "device": "dev", - "grant_type": "gt", - "scope": "openid profile", - }, - ) - @mock.patch("auth0.v3.rest.RestClient.post") def test_signup(self, mock_post): d = Database("my.domain.com", "cid") diff --git a/auth0/v3/test/authentication/test_passwordless.py b/auth0/v3/test/authentication/test_passwordless.py index f384ba8d..b9024f8b 100644 --- a/auth0/v3/test/authentication/test_passwordless.py +++ b/auth0/v3/test/authentication/test_passwordless.py @@ -104,47 +104,3 @@ def test_send_sms_with_client_secret(self, mock_post): "connection": "sms", }, ) - - @mock.patch("auth0.v3.rest.RestClient.post") - def test_send_sms_login(self, mock_post): - - p = Passwordless("my.domain.com", "cid") - - p.sms_login(phone_number="123456", code="abcd") - - args, kwargs = mock_post.call_args - - self.assertEqual(args[0], "https://my.domain.com/oauth/ro") - self.assertEqual( - kwargs["data"], - { - "client_id": "cid", - "connection": "sms", - "grant_type": "password", - "username": "123456", - "password": "abcd", - "scope": "openid", - }, - ) - - @mock.patch("auth0.v3.rest.RestClient.post") - def test_send_sms_login_with_scope(self, mock_post): - - p = Passwordless("my.domain.com", "cid") - - p.sms_login(phone_number="123456", code="abcd", scope="openid profile") - - args, kwargs = mock_post.call_args - - self.assertEqual(args[0], "https://my.domain.com/oauth/ro") - self.assertEqual( - kwargs["data"], - { - "client_id": "cid", - "connection": "sms", - "grant_type": "password", - "username": "123456", - "password": "abcd", - "scope": "openid profile", - }, - ) diff --git a/auth0/v3/test/authentication/test_users.py b/auth0/v3/test/authentication/test_users.py index 60cabeef..0cf2fc35 100644 --- a/auth0/v3/test/authentication/test_users.py +++ b/auth0/v3/test/authentication/test_users.py @@ -17,14 +17,3 @@ def test_userinfo(self, mock_get): url="https://my.domain.com/userinfo", headers={"Authorization": "Bearer atk"}, ) - - @mock.patch("auth0.v3.rest.RestClient.post") - def test_tokeninfo(self, mock_post): - - u = Users("my.domain.com") - - u.tokeninfo(jwt="jwtoken") - - mock_post.assert_called_with( - url="https://my.domain.com/tokeninfo", data={"id_token": "jwtoken"} - ) diff --git a/auth0/v3/test/management/test_jobs.py b/auth0/v3/test/management/test_jobs.py index 5d7d6700..f92d3724 100644 --- a/auth0/v3/test/management/test_jobs.py +++ b/auth0/v3/test/management/test_jobs.py @@ -34,18 +34,6 @@ def test_get_failed_job(self, mock_rc): "https://domain/api/v2/jobs/an-id/errors", ) - @mock.patch("auth0.v3.management.jobs.RestClient") - def test_get_job_results(self, mock_rc): - mock_instance = mock_rc.return_value - - j = Jobs(domain="domain", token="jwttoken") - j.get_results("an-id") - - # Should use the 'get by id' URL - mock_instance.get.assert_called_with( - "https://domain/api/v2/jobs/an-id", - ) - @mock.patch("auth0.v3.management.jobs.RestClient") def test_export_users(self, mock_rc): mock_instance = mock_rc.return_value diff --git a/auth0/v3/test/management/test_users.py b/auth0/v3/test/management/test_users.py index 957dab5b..29924dd0 100644 --- a/auth0/v3/test/management/test_users.py +++ b/auth0/v3/test/management/test_users.py @@ -79,15 +79,6 @@ def test_create(self, mock_rc): self.assertEqual("https://domain/api/v2/users", args[0]) self.assertEqual(kwargs["data"], {"a": "b", "c": "d"}) - @mock.patch("auth0.v3.management.users.RestClient") - def test_delete_all_users(self, mock_rc): - mock_instance = mock_rc.return_value - - u = Users(domain="domain", token="jwttoken") - u.delete_all_users() - - mock_instance.delete.assert_called_with("https://domain/api/v2/users") - @mock.patch("auth0.v3.management.users.RestClient") def test_get(self, mock_rc): mock_instance = mock_rc.return_value diff --git a/auth0/v3/test_async/test_async_token_verifier.py b/auth0/v3/test_async/test_async_token_verifier.py index 7fa6b866..77fc6b57 100644 --- a/auth0/v3/test_async/test_async_token_verifier.py +++ b/auth0/v3/test_async/test_async_token_verifier.py @@ -79,8 +79,13 @@ async def test_async_asymmetric_verifier_fetches_key(self, mocked): ) class TestAsyncJwksFetcher(getattr(unittest, "IsolatedAsyncioTestCase", object)): @aioresponses() - async def test_async_get_jwks_json_twice_on_cache_expired(self, mocked): - fetcher = AsyncJwksFetcher(JWKS_URI, cache_ttl=1) + @unittest.mock.patch( + "auth0.v3.authentication.token_verifier.time.time", return_value=0 + ) + async def test_async_get_jwks_json_twice_on_cache_expired( + self, mocked, mocked_time + ): + fetcher = AsyncJwksFetcher(JWKS_URI, cache_ttl=100) callback, mock = get_callback(200, JWKS_RESPONSE_SINGLE_KEY) mocked.get(JWKS_URI, callback=callback) @@ -99,7 +104,7 @@ async def test_async_get_jwks_json_twice_on_cache_expired(self, mocked): ) self.assertEqual(mock.call_count, 1) - time.sleep(2) + mocked_time.return_value = 200 # 2 seconds has passed, cache should be expired key_1 = await fetcher.get_key("test-key-1")