usso 0.24.6__tar.gz → 0.24.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {usso-0.24.6/src/usso.egg-info → usso-0.24.8}/PKG-INFO +1 -1
- {usso-0.24.6 → usso-0.24.8}/pyproject.toml +1 -1
- usso-0.24.8/src/usso/async_session.py +86 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/fastapi/integration.py +1 -1
- {usso-0.24.6 → usso-0.24.8/src/usso.egg-info}/PKG-INFO +1 -1
- usso-0.24.6/src/usso/async_session.py +0 -48
- {usso-0.24.6 → usso-0.24.8}/LICENSE.txt +0 -0
- {usso-0.24.6 → usso-0.24.8}/README.md +0 -0
- {usso-0.24.6 → usso-0.24.8}/setup.cfg +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/__init__.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/api.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/async_api.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/b64tools.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/core.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/django/__init__.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/django/middleware.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/exceptions.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/fastapi/__init__.py +1 -1
- {usso-0.24.6 → usso-0.24.8}/src/usso/package_data.dat +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso/session.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso.egg-info/SOURCES.txt +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso.egg-info/dependency_links.txt +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso.egg-info/entry_points.txt +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso.egg-info/requires.txt +0 -0
- {usso-0.24.6 → usso-0.24.8}/src/usso.egg-info/top_level.txt +0 -0
- {usso-0.24.6 → usso-0.24.8}/tests/test_api.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/tests/test_core.py +0 -0
- {usso-0.24.6 → usso-0.24.8}/tests/test_simple.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: usso
|
3
|
-
Version: 0.24.
|
3
|
+
Version: 0.24.8
|
4
4
|
Summary: A plug-and-play client for integrating universal single sign-on (SSO) with Python frameworks, enabling secure and seamless authentication across microservices.
|
5
5
|
Author-email: Mahdi Kiani <mahdikiany@gmail.com>
|
6
6
|
Maintainer-email: Mahdi Kiani <mahdikiany@gmail.com>
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "usso"
|
7
|
-
version = "0.24.
|
7
|
+
version = "0.24.8"
|
8
8
|
description = "A plug-and-play client for integrating universal single sign-on (SSO) with Python frameworks, enabling secure and seamless authentication across microservices."
|
9
9
|
readme = "README.md"
|
10
10
|
requires-python = ">=3.9"
|
@@ -0,0 +1,86 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
import aiohttp
|
3
|
+
import jwt
|
4
|
+
|
5
|
+
|
6
|
+
class AsyncUssoSession:
|
7
|
+
def __init__(self, sso_refresh_url: str, refresh_token: str | None = None):
|
8
|
+
self.sso_refresh_url = sso_refresh_url
|
9
|
+
self.refresh_token = refresh_token
|
10
|
+
self.access_token = None
|
11
|
+
self.session = None # This will hold the aiohttp session
|
12
|
+
|
13
|
+
async def _refresh(self):
|
14
|
+
if not self.refresh_token:
|
15
|
+
raise ValueError("Refresh token not provided or invalid.")
|
16
|
+
|
17
|
+
async with aiohttp.ClientSession() as session:
|
18
|
+
async with session.post(
|
19
|
+
self.sso_refresh_url,
|
20
|
+
json={"refresh_token": self.refresh_token},
|
21
|
+
) as response:
|
22
|
+
response.raise_for_status()
|
23
|
+
return await response.json()
|
24
|
+
|
25
|
+
async def _ensure_valid_token(self):
|
26
|
+
if self.access_token:
|
27
|
+
decoded_token = jwt.decode(
|
28
|
+
self.access_token, options={"verify_signature": False}
|
29
|
+
)
|
30
|
+
exp = decoded_token.get("exp")
|
31
|
+
|
32
|
+
if exp and datetime.fromtimestamp(exp) < datetime.now():
|
33
|
+
self.access_token = None # Token expired, need a new one
|
34
|
+
|
35
|
+
if not self.access_token:
|
36
|
+
# Get a new token if none exists or it has expired
|
37
|
+
token_data = await self._refresh()
|
38
|
+
self.access_token = token_data["access_token"]
|
39
|
+
|
40
|
+
# Update headers with the new access token
|
41
|
+
if self.session:
|
42
|
+
self.session.headers.update(
|
43
|
+
{"Authorization": f"Bearer {self.access_token}"}
|
44
|
+
)
|
45
|
+
|
46
|
+
async def __aenter__(self):
|
47
|
+
self.session = aiohttp.ClientSession() # Initialize the session
|
48
|
+
await self._ensure_valid_token() # Ensure valid token before usage
|
49
|
+
return self
|
50
|
+
|
51
|
+
async def __aexit__(self, exc_type, exc_value, traceback):
|
52
|
+
if self.session:
|
53
|
+
await self.session.close() # Close the session properly
|
54
|
+
|
55
|
+
async def _request(self, method: str, url: str, **kwargs):
|
56
|
+
await self._ensure_valid_token() # Ensure valid token before any request
|
57
|
+
return await self.session.request(method, url, **kwargs)
|
58
|
+
|
59
|
+
async def get(self, url: str, **kwargs):
|
60
|
+
return await self._request("GET", url, **kwargs)
|
61
|
+
|
62
|
+
async def post(self, url: str, **kwargs):
|
63
|
+
return await self._request("POST", url, **kwargs)
|
64
|
+
|
65
|
+
async def put(self, url: str, **kwargs):
|
66
|
+
return await self._request("PUT", url, **kwargs)
|
67
|
+
|
68
|
+
async def patch(self, url: str, **kwargs):
|
69
|
+
return await self._request("PATCH", url, **kwargs)
|
70
|
+
|
71
|
+
async def delete(self, url: str, **kwargs):
|
72
|
+
return await self._request("DELETE", url, **kwargs)
|
73
|
+
|
74
|
+
async def head(self, url: str, **kwargs):
|
75
|
+
return await self._request("HEAD", url, **kwargs)
|
76
|
+
|
77
|
+
async def options(self, url: str, **kwargs):
|
78
|
+
return await self._request("OPTIONS", url, **kwargs)
|
79
|
+
|
80
|
+
async def close(self):
|
81
|
+
await self.session.close()
|
82
|
+
self.session = None
|
83
|
+
|
84
|
+
async def __del__(self):
|
85
|
+
if self.session:
|
86
|
+
await self.session.close()
|
@@ -12,7 +12,7 @@ logger = logging.getLogger("usso")
|
|
12
12
|
def get_request_token(request: Request | WebSocket) -> UserData | None:
|
13
13
|
authorization = request.headers.get("Authorization")
|
14
14
|
token = None
|
15
|
-
|
15
|
+
|
16
16
|
if authorization:
|
17
17
|
scheme, credentials = Usso().get_authorization_scheme_param(authorization)
|
18
18
|
if scheme.lower() == "bearer":
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: usso
|
3
|
-
Version: 0.24.
|
3
|
+
Version: 0.24.8
|
4
4
|
Summary: A plug-and-play client for integrating universal single sign-on (SSO) with Python frameworks, enabling secure and seamless authentication across microservices.
|
5
5
|
Author-email: Mahdi Kiani <mahdikiany@gmail.com>
|
6
6
|
Maintainer-email: Mahdi Kiani <mahdikiany@gmail.com>
|
@@ -1,48 +0,0 @@
|
|
1
|
-
from datetime import datetime
|
2
|
-
|
3
|
-
import aiohttp
|
4
|
-
import jwt
|
5
|
-
|
6
|
-
|
7
|
-
class AsyncUssoSession(aiohttp.ClientSession):
|
8
|
-
def __init__(
|
9
|
-
self, sso_refresh_url: str, refresh_token: str | None = None, **kwargs
|
10
|
-
):
|
11
|
-
super().__init__(**kwargs)
|
12
|
-
self.sso_refresh_url = sso_refresh_url
|
13
|
-
self.refresh_token = refresh_token
|
14
|
-
self.access_token = None
|
15
|
-
|
16
|
-
async def _refresh(self):
|
17
|
-
if not self.refresh_token:
|
18
|
-
raise ValueError("Refresh token not provided or invalid.")
|
19
|
-
|
20
|
-
async with aiohttp.ClientSession() as session:
|
21
|
-
async with session.post(
|
22
|
-
self.sso_refresh_url,
|
23
|
-
json={"refresh_token": self.refresh_token},
|
24
|
-
) as response:
|
25
|
-
response.raise_for_status()
|
26
|
-
return await response.json()
|
27
|
-
|
28
|
-
async def _ensure_valid_token(self):
|
29
|
-
if self.access_token:
|
30
|
-
decoded_token = jwt.decode(
|
31
|
-
self.access_token, options={"verify_signature": False}
|
32
|
-
)
|
33
|
-
exp = datetime.fromtimestamp(decoded_token.get("exp"))
|
34
|
-
if exp < datetime.now():
|
35
|
-
self.access_token = None
|
36
|
-
|
37
|
-
if not self.access_token:
|
38
|
-
token_data = await self._refresh()
|
39
|
-
self.access_token = token_data["access_token"]
|
40
|
-
|
41
|
-
self.headers.update({"Authorization": f"Bearer {self.access_token}"})
|
42
|
-
|
43
|
-
async def __aenter__(self):
|
44
|
-
await self._ensure_valid_token()
|
45
|
-
return self
|
46
|
-
|
47
|
-
async def __aexit__(self, exc_type, exc_value, traceback):
|
48
|
-
await self.close()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|