Skip to content

Commit

Permalink
Add option to save and load request_token
Browse files Browse the repository at this point in the history
  • Loading branch information
Antoni-Czaplicki committed Jul 7, 2024
1 parent 8c4989d commit b94194f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 23 deletions.
4 changes: 2 additions & 2 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ The USOS API uses OAuth 1.0a for authentication. The ``USOSClient`` class provid
async with USOSClient(api_base_address, consumer_key, consumer_secret) as client:
print(await client.get_authorization_url()) # Open this URL in your browser, by default no callback URL is needed and you can just copy the PIN from the page you are redirected to
token = input("Enter the PIN: ")
await client.authorize(token)
verifier = input("Enter the PIN: ")
await client.authorize(verifier)
Basic Usage
-----------
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "usos-api"
version = "0.1.1"
version = "0.1.2"
description = "Asynchronous USOS API for Python"
authors = ["Antoni-Czaplicki <[email protected]>"]
readme = "README.md"
Expand Down
4 changes: 2 additions & 2 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ async def fetch_data(api_base_address: str, consumer_key: str, consumer_secret:
print("Please visit the following URL to authorize the client:")
client.set_scopes(["studies", "photo"])
print(await client.get_authorization_url())
token = input("Enter the PIN: ")
await client.authorize(token)
verifier = input("Enter the PIN: ")
await client.authorize(verifier)
await client.save_access_token_to_file()

user = await client.user_service.get_user()
Expand Down
43 changes: 31 additions & 12 deletions usos_api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,37 @@ async def get_authorization_url(self, callback_url: str) -> str:
await self._generate_request_token(callback_url)
return f"{self.base_address}{self.AUTHORIZE_SUFFIX}?oauth_token={self._request_token}"

async def authorize_with_token(self, token: str) -> tuple[str, str]:
async def authorize(self, verifier: str, request_token, request_token_secret):
"""
Authorize the client with a token.
Authorize the client with verifier and optionally token and token secret.
:param token: The token to authorize the client with.
:param verifier: The verifier to authorize the client with.
:param token: The OAuth token obtained from the previous step.
:param token_secret: The OAuth token secret obtained from the previous step.
:return: The access token and secret.
"""
self._oauth_client.verifier = token
self._oauth_client.verifier = verifier
if request_token:
self._oauth_client.resource_owner_key = request_token
if request_token_secret:
self._oauth_client.resource_owner_secret = request_token_secret
url = f"{self.base_address}{self.ACCESS_TOKEN_SUFFIX}"
url, headers, body = self._oauth_client.sign(url, http_method="POST")
async with self._session.post(url, data=body, headers=headers) as response:
await self._handle_response_errors(response)
data = dict(urllib.parse.parse_qsl(await response.text()))
self.load_access_token(data["oauth_token"], data["oauth_token_secret"])
_LOGGER.info(
f"Authorization successful, received access token: {self.access_token}"
)
return self.access_token, self.access_token_secret
try:
async with self._session.post(url, data=body, headers=headers) as response:
await self._handle_response_errors(response)
data = dict(urllib.parse.parse_qsl(await response.text()))
self.load_access_token(data["oauth_token"], data["oauth_token_secret"])
_LOGGER.info(
f"Authorization successful, received access token: {self.access_token}"
)
return self.access_token, self.access_token_secret
except AttributeError as e:
if e.args[0] == "'NoneType' object has no attribute 'post'":
raise USOSAPIException(
"Authorization failed. Did you forget to open the manager?"
)
raise

def load_access_token(self, access_token: str, access_token_secret: str):
"""
Expand All @@ -138,6 +151,12 @@ def load_access_token(self, access_token: str, access_token_secret: str):
resource_owner_secret=self.access_token_secret,
)

def get_access_token(self):
return self.access_token, self.access_token_secret

def get_request_token(self):
return self._request_token, self._request_token_secret

def sign_request(
self, url: str, http_method: str = "GET", **kwargs
) -> tuple[str, dict, dict]:
Expand Down
17 changes: 11 additions & 6 deletions usos_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,18 @@ def remove_scope(self, scope: str) -> None:
[s for s in self.connection.auth_manager.SCOPES.split("|") if s != scope]
)

async def authorize(self, token: str) -> tuple[str, str]:
async def authorize(self, verifier: str, request_token: str = None, request_token_secret: str = None) -> tuple[str, str]:
"""
Authorize the client with a token.
Authorize the client with verifier and optionally token and token secret.
:param token: The token to authorize the client with.
Parameters `token` and `token_secret` can be useful when you create a new client instance and want to authorize it with the token and secret obtained from another client instance.
:param verifier: The verifier to authorize the client with.
:param request_token: The OAuth token obtained from the previous step.
:param request_token_secret: The OAuth token secret obtained from the previous step.
:return: The access token and secret.
"""
return await self.connection.auth_manager.authorize_with_token(token)
return await self.connection.auth_manager.authorize(verifier, request_token, request_token_secret)

async def get_authorization_url(self, callback_url: str = "oob"):
"""
Expand Down Expand Up @@ -160,9 +164,10 @@ async def save_access_token_to_file(
"""
if not file_path.endswith(".json"):
raise ValueError("File must be a JSON file.")
access_token, access_token_secret = self.connection.auth_manager.get_access_token()
json_data = {
"access_token": self.connection.auth_manager.access_token,
"access_token_secret": self.connection.auth_manager.access_token_secret,
"access_token": access_token,
"access_token_secret": access_token_secret,
}
with open(file_path, "w") as file:
json.dump(json_data, file)
Expand Down

0 comments on commit b94194f

Please sign in to comment.