Repository: kapadia/usgs

Issue:
Deprecated usgs login endpoint to login-token endpoint
The current `login` endpoint, which is used for authentication within the API, will be deprecated in February of 2025. Users are encouraged to create one or more M2M Application Tokens and to transition to using the `login-token` endpoint in lieu of the current login endpoint prior to February 2025. This will allow for continued data access. The USGS has created a document to aid users in the creation and use of an Application Token. More details are available here: [https://www.usgs.gov/media/files/m2m-application-token-documentation](https://www.usgs.gov/media/files/m2m-application-token-documentation)

Discussion:
@kapadia: Hi @BRrodrigots, thanks for raising the issue of the deprecating endpoint. I'm curious whether there are many users of this library at this point in time. If so, I can make the changes sooner rather than later.@chpolste: In the CLIMAAX project we would appreciate if the usgs backend of eodag keeps working! Only small changes to the login payload and api endpoint are necessary, see #75.@klimeto: We do use it also at JRC BDAP project together with EODAG and would appreciate a lot if we can continue in doing so.@floriandeboissieu: @kapadia now that PR #75 has been merged into branch `master`, it would be nice to bump the version number and/or to push these changes to pypi and conda-forge.

@klimeto the workaround until new version is to force reinstall of package `usgs` after installing `eodag`:
```
pip install --force-reinstall --no-deps git+https://github.com/kapadia/usgs
```
@kalxas: @kapadia a new release would be much appreciated.@kapadia: @kalxas thanks for the nudge. You can find a new release on PyPI: https://pypi.org/project/usgs@kalxas: Many thanks @kapadia 
A git tag would also help this release to get picked up by Debian:
https://salsa.debian.org/debian-gis-team/usgs@kapadia: @kalxas A new tag and release are available: https://github.com/kapadia/usgs/releases/tag/v0.3.6@kalxas: Thank you @kapadia 
Cheers!

Solution patch:
diff --git a/usgs/api.py b/usgs/api.py
index d4b8af0..bd3da60 100644
--- a/usgs/api.py
+++ b/usgs/api.py
@@ -136,19 +136,19 @@ def dataset_search(dataset=None, catalog=None, ll=None, ur=None, start_date=None
 
     return response
 
-def login(username, password, save=True):
+def login(username, token, save=True):
     """
     Log in, creating a temporary API key and optionally storing it for later use.
 
     :param str username: Username of the USGS account to log in with.
-    :param str password: Password of the USGS account to log in with.
+    :param str token: Application Token of the USGS account to log in with.
     :param bool save: If true, the API key will be stored in a local file (~/.usgs)
         until `api.logout` is called to remove it. The stored key will be used by
         other functions to authenticate requests whenever an API key is not explicitly
         provided.
     """
-    url = '{}/login'.format(USGS_API)
-    payload = payloads.login(username, password)
+    url = '{}/login-token'.format(USGS_API)
+    payload = payloads.login(username, token)
 
     with _create_session(api_key=None) as session:
         created = datetime.now().isoformat()
diff --git a/usgs/payloads.py b/usgs/payloads.py
index 443d187..8cf7454 100644
--- a/usgs/payloads.py
+++ b/usgs/payloads.py
@@ -124,18 +124,18 @@ def dataset_search(dataset, catalog, start_date=None, end_date=None, ll=None, ur
 
     return json.dumps(payload)
 
-def login(username, password):
+def login(username, token):
     """
     Upon a successful login, an API key will be returned. This key will be active
     for two hours and should be destroyed upon final use of the service by calling
     the logout method.
 
     :param str username:
-    :param str password:
+    :param str token:
     """
     payload = {
         "username": username,
-        "password": password
+        "token": token
     }
 
     return json.dumps(payload)
diff --git a/usgs/scripts/cli.py b/usgs/scripts/cli.py
index c66b7cf..77fe618 100644
--- a/usgs/scripts/cli.py
+++ b/usgs/scripts/cli.py
@@ -84,8 +84,8 @@ def usgs():
 
 @click.command()
 @click.argument("username", envvar='USGS_USERNAME')
-@click.argument("password", envvar='USGS_PASSWORD')
-def cycle_token(username, password):
+@click.argument("token", envvar='USGS_TOKEN')
+def cycle_token(username, token):
 
     credential_filepath = os.path.join(os.path.expanduser("~"), ".usgs")
     with open(credential_filepath) as f:
@@ -97,7 +97,7 @@ def cycle_token(username, password):
     click.echo('The token lifetime is {} seconds'.format(token_lifetime))
     if token_lifetime > approx_two_hours:
         api.logout()
-        api.login(username, password)
+        api.login(username, token)
 
 
 @click.command()
@@ -139,9 +139,9 @@ def download_request(dataset, entity_id, product_id, api_key):
 
 @click.command()
 @click.argument("username", envvar='USGS_USERNAME')
-@click.argument("password", envvar='USGS_PASSWORD')
-def login(username, password):
-    click.echo(api.login(username, password))
+@click.argument("token", envvar='USGS_TOKEN')
+def login(username, token):
+    click.echo(api.login(username, token))
 
 
 @click.command()


Test patch:
diff --git a/tests/create_snapshots.py b/tests/create_snapshots.py
index 11e2b02..6620377 100644
--- a/tests/create_snapshots.py
+++ b/tests/create_snapshots.py
@@ -17,7 +17,7 @@ def create_snapshots():
     Run requests against USGS API for use in tests.
     """
 
-    api_key = api.login(os.environ['USGS_USERNAME'], os.environ['USGS_PASSWORD'])
+    api_key = api.login(os.environ['USGS_USERNAME'], os.environ['USGS_TOKEN'])
 
     # Dataset Fields
     response = api.dataset_fields("LANDSAT_8_C1", "EE", api_key=api_key)
diff --git a/tests/test_payloads.py b/tests/test_payloads.py
index 620e67b..50d5ff5 100644
--- a/tests/test_payloads.py
+++ b/tests/test_payloads.py
@@ -54,8 +54,8 @@ class PayloadsTest(unittest.TestCase):
 
     
     def test_login(self):
-        expected = """{"username": "username", "password": "password"}"""
-        payload = payloads.login("username", "password")
+        expected = """{"username": "username", "token": "token"}"""
+        payload = payloads.login("username", "token")
         assert compare_json(payload, expected)