usso 0.24.11__py3-none-any.whl → 0.24.12__py3-none-any.whl
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/async_session.py +34 -4
- usso/core.py +18 -31
- usso/fastapi/auth_middleware.py +40 -30
- usso/session.py +34 -4
- {usso-0.24.11.dist-info → usso-0.24.12.dist-info}/METADATA +1 -1
- {usso-0.24.11.dist-info → usso-0.24.12.dist-info}/RECORD +10 -10
- {usso-0.24.11.dist-info → usso-0.24.12.dist-info}/LICENSE.txt +0 -0
- {usso-0.24.11.dist-info → usso-0.24.12.dist-info}/WHEEL +0 -0
- {usso-0.24.11.dist-info → usso-0.24.12.dist-info}/entry_points.txt +0 -0
- {usso-0.24.11.dist-info → usso-0.24.12.dist-info}/top_level.txt +0 -0
usso/async_session.py
CHANGED
@@ -1,21 +1,51 @@
|
|
1
1
|
from contextlib import asynccontextmanager
|
2
|
-
from datetime import datetime
|
2
|
+
from datetime import datetime, timedelta
|
3
3
|
|
4
4
|
import aiohttp
|
5
5
|
import jwt
|
6
6
|
|
7
7
|
|
8
8
|
class AsyncUssoSession:
|
9
|
-
def __init__(
|
9
|
+
def __init__(
|
10
|
+
self,
|
11
|
+
sso_refresh_url: str,
|
12
|
+
refresh_token: str | None = None,
|
13
|
+
api_key: str | None = None,
|
14
|
+
):
|
10
15
|
self.sso_refresh_url = sso_refresh_url
|
11
|
-
self.
|
16
|
+
self._refresh_token = refresh_token
|
12
17
|
self.access_token = None
|
13
18
|
self.session = None # This will hold the aiohttp session
|
19
|
+
self.api_key = api_key
|
20
|
+
|
21
|
+
@property
|
22
|
+
def refresh_token(self):
|
23
|
+
decoded_token = jwt.decode(
|
24
|
+
self._refresh_token, options={"verify_signature": False}
|
25
|
+
)
|
26
|
+
exp = decoded_token.get("exp", datetime.now() + timedelta(days=1))
|
27
|
+
if exp < datetime.now():
|
28
|
+
self._refresh_token = None
|
29
|
+
|
30
|
+
return self._refresh_token
|
31
|
+
|
32
|
+
async def _refresh_api(self):
|
33
|
+
async with aiohttp.ClientSession() as session:
|
34
|
+
async with session.get(
|
35
|
+
f"{self.sso_refresh_url}/api",
|
36
|
+
headers={"x-api-key": self.api_key},
|
37
|
+
) as response:
|
38
|
+
response.raise_for_status()
|
39
|
+
data: dict = await response.json()
|
40
|
+
self._refresh_token = data.get("token", {}).get("refresh_token")
|
14
41
|
|
15
42
|
async def _refresh(self):
|
16
|
-
if not self.refresh_token:
|
43
|
+
if not self.refresh_token and not self.api_key:
|
17
44
|
raise ValueError("Refresh token not provided or invalid.")
|
18
45
|
|
46
|
+
if self.api_key and not self.refresh_token:
|
47
|
+
self._refresh_api()
|
48
|
+
|
19
49
|
async with aiohttp.ClientSession() as session:
|
20
50
|
async with session.post(
|
21
51
|
self.sso_refresh_url,
|
usso/core.py
CHANGED
@@ -64,23 +64,11 @@ class Usso(metaclass=Singleton):
|
|
64
64
|
scheme, _, param = authorization_header_value.partition(" ")
|
65
65
|
return scheme, param
|
66
66
|
|
67
|
-
def
|
68
|
-
"""Return the user associated with a token value."""
|
67
|
+
def decode_token(self, key, token: str, **kwargs) -> dict:
|
69
68
|
try:
|
70
|
-
|
71
|
-
# jwks_url = header["jwk_url"]
|
72
|
-
jwks_client = self.get_jwks_keys()
|
73
|
-
signing_key = jwks_client.get_signing_key_from_jwt(token)
|
74
|
-
decoded = jwt.decode(
|
75
|
-
token,
|
76
|
-
signing_key.key,
|
77
|
-
algorithms=["RS256"],
|
78
|
-
)
|
69
|
+
decoded = jwt.decode(token, key, algorithms=["RS256"])
|
79
70
|
if decoded["token_type"] != "access":
|
80
|
-
raise USSOException(
|
81
|
-
status_code=401,
|
82
|
-
error="invalid_token_type",
|
83
|
-
)
|
71
|
+
raise USSOException(status_code=401, error="invalid_token_type")
|
84
72
|
decoded["token"] = token
|
85
73
|
return UserData(**decoded)
|
86
74
|
except jwt.exceptions.ExpiredSignatureError:
|
@@ -91,31 +79,30 @@ class Usso(metaclass=Singleton):
|
|
91
79
|
raise USSOException(status_code=401, error="invalid_signature")
|
92
80
|
except jwt.exceptions.InvalidAlgorithmError:
|
93
81
|
if kwargs.get("raise_exception", True):
|
94
|
-
raise USSOException(
|
95
|
-
status_code=401,
|
96
|
-
error="invalid_algorithm",
|
97
|
-
)
|
82
|
+
raise USSOException(status_code=401, error="invalid_algorithm")
|
98
83
|
except jwt.exceptions.InvalidIssuedAtError:
|
99
84
|
if kwargs.get("raise_exception", True):
|
100
|
-
raise USSOException(
|
101
|
-
status_code=401,
|
102
|
-
error="invalid_issued_at",
|
103
|
-
)
|
85
|
+
raise USSOException(status_code=401, error="invalid_issued_at")
|
104
86
|
except jwt.exceptions.InvalidTokenError:
|
105
87
|
if kwargs.get("raise_exception", True):
|
106
|
-
raise USSOException(
|
107
|
-
status_code=401,
|
108
|
-
error="invalid_token",
|
109
|
-
)
|
88
|
+
raise USSOException(status_code=401, error="invalid_token")
|
110
89
|
except jwt.exceptions.InvalidKeyError:
|
111
90
|
if kwargs.get("raise_exception", True):
|
112
|
-
raise USSOException(
|
113
|
-
status_code=401,
|
114
|
-
error="invalid_key",
|
115
|
-
)
|
91
|
+
raise USSOException(status_code=401, error="invalid_key")
|
116
92
|
except USSOException as e:
|
117
93
|
if kwargs.get("raise_exception", True):
|
118
94
|
raise e
|
95
|
+
except Exception as e:
|
96
|
+
if kwargs.get("raise_exception", True):
|
97
|
+
raise USSOException(status_code=401, error="error", message=str(e))
|
98
|
+
logger.error(e)
|
99
|
+
|
100
|
+
def user_data_from_token(self, token: str, **kwargs) -> UserData | None:
|
101
|
+
"""Return the user associated with a token value."""
|
102
|
+
try:
|
103
|
+
jwks_client = self.get_jwks_keys()
|
104
|
+
signing_key = jwks_client.get_signing_key_from_jwt(token)
|
105
|
+
return self.decode_token(signing_key.key, token, **kwargs)
|
119
106
|
except Exception as e:
|
120
107
|
if kwargs.get("raise_exception", True):
|
121
108
|
raise USSOException(
|
usso/fastapi/auth_middleware.py
CHANGED
@@ -73,15 +73,45 @@ class Usso:
|
|
73
73
|
scheme, _, param = authorization_header_value.partition(" ")
|
74
74
|
return scheme, param
|
75
75
|
|
76
|
+
def decode_token(self, key, token: str, **kwargs) -> dict:
|
77
|
+
try:
|
78
|
+
decoded = jwt.decode(token, key, algorithms=["RS256"])
|
79
|
+
if decoded["token_type"] != "access":
|
80
|
+
raise USSOException(status_code=401, error="invalid_token_type")
|
81
|
+
decoded["token"] = token
|
82
|
+
return UserData(**decoded)
|
83
|
+
except jwt.exceptions.ExpiredSignatureError:
|
84
|
+
if kwargs.get("raise_exception", True):
|
85
|
+
raise USSOException(status_code=401, error="expired_signature")
|
86
|
+
except jwt.exceptions.InvalidSignatureError:
|
87
|
+
if kwargs.get("raise_exception", True):
|
88
|
+
raise USSOException(status_code=401, error="invalid_signature")
|
89
|
+
except jwt.exceptions.InvalidAlgorithmError:
|
90
|
+
if kwargs.get("raise_exception", True):
|
91
|
+
raise USSOException(status_code=401, error="invalid_algorithm")
|
92
|
+
except jwt.exceptions.InvalidIssuedAtError:
|
93
|
+
if kwargs.get("raise_exception", True):
|
94
|
+
raise USSOException(status_code=401, error="invalid_issued_at")
|
95
|
+
except jwt.exceptions.InvalidTokenError:
|
96
|
+
if kwargs.get("raise_exception", True):
|
97
|
+
raise USSOException(status_code=401, error="invalid_token")
|
98
|
+
except jwt.exceptions.InvalidKeyError:
|
99
|
+
if kwargs.get("raise_exception", True):
|
100
|
+
raise USSOException(status_code=401, error="invalid_key")
|
101
|
+
except USSOException as e:
|
102
|
+
if kwargs.get("raise_exception", True):
|
103
|
+
raise e
|
104
|
+
except Exception as e:
|
105
|
+
if kwargs.get("raise_exception", True):
|
106
|
+
raise USSOException(status_code=401, error="error", message=str(e))
|
107
|
+
logger.error(e)
|
108
|
+
|
76
109
|
def user_data_from_token(self, token: str, **kwargs) -> UserData | None:
|
77
110
|
"""Return the user associated with a token value."""
|
78
111
|
try:
|
79
112
|
decoded = self.jwk_url.decode(token)
|
80
113
|
if decoded["token_type"] != "access":
|
81
|
-
raise USSOException(
|
82
|
-
status_code=401,
|
83
|
-
error="invalid_token_type",
|
84
|
-
)
|
114
|
+
raise USSOException(status_code=401, error="invalid_token_type")
|
85
115
|
decoded["token"] = token
|
86
116
|
return UserData(**decoded)
|
87
117
|
except jwt.exceptions.ExpiredSignatureError:
|
@@ -92,45 +122,25 @@ class Usso:
|
|
92
122
|
raise USSOException(status_code=401, error="invalid_signature")
|
93
123
|
except jwt.exceptions.InvalidAlgorithmError:
|
94
124
|
if kwargs.get("raise_exception", True):
|
95
|
-
raise USSOException(
|
96
|
-
status_code=401,
|
97
|
-
error="invalid_algorithm",
|
98
|
-
)
|
125
|
+
raise USSOException(status_code=401, error="invalid_algorithm")
|
99
126
|
except jwt.exceptions.InvalidIssuedAtError:
|
100
127
|
if kwargs.get("raise_exception", True):
|
101
|
-
raise USSOException(
|
102
|
-
status_code=401,
|
103
|
-
error="invalid_issued_at",
|
104
|
-
)
|
128
|
+
raise USSOException(status_code=401, error="invalid_issued_at")
|
105
129
|
except jwt.exceptions.InvalidTokenError:
|
106
130
|
if kwargs.get("raise_exception", True):
|
107
|
-
raise USSOException(
|
108
|
-
status_code=401,
|
109
|
-
error="invalid_token",
|
110
|
-
)
|
131
|
+
raise USSOException(status_code=401, error="invalid_token")
|
111
132
|
except jwt.exceptions.InvalidKeyError:
|
112
133
|
if kwargs.get("raise_exception", True):
|
113
|
-
raise USSOException(
|
114
|
-
status_code=401,
|
115
|
-
error="invalid_key",
|
116
|
-
)
|
134
|
+
raise USSOException(status_code=401, error="invalid_key")
|
117
135
|
except KeyError as e:
|
118
136
|
if kwargs.get("raise_exception", True):
|
119
|
-
raise USSOException(
|
120
|
-
status_code=401,
|
121
|
-
error="key_error",
|
122
|
-
message=str(e),
|
123
|
-
)
|
137
|
+
raise USSOException(status_code=401, error="key_error", message=str(e))
|
124
138
|
except USSOException as e:
|
125
139
|
if kwargs.get("raise_exception", True):
|
126
140
|
raise e
|
127
141
|
except Exception as e:
|
128
142
|
if kwargs.get("raise_exception", True):
|
129
|
-
raise USSOException(
|
130
|
-
status_code=401,
|
131
|
-
error="error",
|
132
|
-
message=str(e),
|
133
|
-
)
|
143
|
+
raise USSOException(status_code=401, error="error", message=str(e))
|
134
144
|
logger.error(e)
|
135
145
|
|
136
146
|
async def jwt_access_security(self, request: Request) -> UserData | None:
|
usso/session.py
CHANGED
@@ -1,19 +1,49 @@
|
|
1
|
-
from datetime import datetime
|
1
|
+
from datetime import datetime, timedelta
|
2
2
|
|
3
3
|
import jwt
|
4
4
|
import requests
|
5
5
|
|
6
6
|
|
7
7
|
class UssoSession:
|
8
|
-
|
8
|
+
|
9
|
+
def __init__(
|
10
|
+
self,
|
11
|
+
sso_refresh_url: str,
|
12
|
+
refresh_token: str | None = None,
|
13
|
+
api_key: str | None = None,
|
14
|
+
):
|
9
15
|
self.sso_refresh_url = sso_refresh_url
|
10
|
-
self.
|
16
|
+
self._refresh_token = refresh_token
|
11
17
|
self.session = requests.Session()
|
12
18
|
self.access_token = None
|
19
|
+
self.api_key = api_key
|
20
|
+
|
21
|
+
@property
|
22
|
+
def refresh_token(self):
|
23
|
+
decoded_token = jwt.decode(
|
24
|
+
self._refresh_token, options={"verify_signature": False}
|
25
|
+
)
|
26
|
+
exp = decoded_token.get("exp", datetime.now() + timedelta(days=1))
|
27
|
+
if exp < datetime.now():
|
28
|
+
self._refresh_token = None
|
29
|
+
|
30
|
+
return self._refresh_token
|
31
|
+
|
32
|
+
def _refresh_api(self):
|
33
|
+
response = requests.get(
|
34
|
+
f"{self.sso_refresh_url}/api",
|
35
|
+
headers={"x-api-key": self.api_key},
|
36
|
+
)
|
37
|
+
response.raise_for_status()
|
38
|
+
data = response.json()
|
39
|
+
self._refresh_token = data.get("token", {}).get("refresh_token")
|
13
40
|
|
14
41
|
def _refresh(self):
|
15
|
-
if not self.refresh_token:
|
42
|
+
if not self.refresh_token and not self.api_key:
|
16
43
|
return
|
44
|
+
|
45
|
+
if self.api_key and not self.refresh_token:
|
46
|
+
self._refresh_api()
|
17
47
|
|
18
48
|
response = requests.post(
|
19
49
|
self.sso_refresh_url,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: usso
|
3
|
-
Version: 0.24.
|
3
|
+
Version: 0.24.12
|
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,20 +1,20 @@
|
|
1
1
|
usso/__init__.py,sha256=NnOS_S1a-JKTOlGe1nw-kCL3m0y82mA2mDraus7BQ2o,120
|
2
2
|
usso/api.py,sha256=xlDq2nZNpq3mhAvqIbGEfANHNjJpPquSeULBfS7iMJw,5094
|
3
3
|
usso/async_api.py,sha256=rb-Xh5oudmZrPYM_iH_B75b5Z0Fvi1V1uurdcKE51w0,5551
|
4
|
-
usso/async_session.py,sha256=
|
4
|
+
usso/async_session.py,sha256=whaxQjR1tkarOljknrhNyPAS5sHvYasBszvd0_MoN3Q,4015
|
5
5
|
usso/b64tools.py,sha256=HGQ0E59vzjrQo2-4jrcY03ebtTaYwTtCZ7KgJaEmxO0,610
|
6
|
-
usso/core.py,sha256=
|
6
|
+
usso/core.py,sha256=cOpETK_gGVsUJT0EeIebOGLEbF8vHVET-_I-8QxOCyE,3977
|
7
7
|
usso/exceptions.py,sha256=hawOAuVbvQtjgRfwp1KFZ4SmV7fh720y5Gom9JVA8W8,504
|
8
8
|
usso/package_data.dat,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
usso/session.py,sha256=
|
9
|
+
usso/session.py,sha256=4KFePzs9gjtoPOpcrKR8A-GWtUF3zhVBAAWzKaA3lm8,2055
|
10
10
|
usso/django/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
usso/django/middleware.py,sha256=EEEpHvMQ6QiWw2HY8zQ2Aec0RCATcLWsCKeyiPWJKio,3245
|
12
12
|
usso/fastapi/__init__.py,sha256=0EcdOzb4f3yu9nILIdGWnlyUz-0VaVX2az1e3f2BusI,201
|
13
|
-
usso/fastapi/auth_middleware.py,sha256=
|
13
|
+
usso/fastapi/auth_middleware.py,sha256=DYrNPy_9FIV1amRuafoJtgGMi8uE0FPmSKBUGP79GNo,7616
|
14
14
|
usso/fastapi/integration.py,sha256=VAUWaa7ChQ1jTtn8A136VgyG6t2kDo5pGK-3RgmNDVs,1669
|
15
|
-
usso-0.24.
|
16
|
-
usso-0.24.
|
17
|
-
usso-0.24.
|
18
|
-
usso-0.24.
|
19
|
-
usso-0.24.
|
20
|
-
usso-0.24.
|
15
|
+
usso-0.24.12.dist-info/LICENSE.txt,sha256=ceC9ZJOV9H6CtQDcYmHOS46NA3dHJ_WD4J9blH513pc,1081
|
16
|
+
usso-0.24.12.dist-info/METADATA,sha256=3ZTqFGl6CCBk-YIXYsDy6IECFv1nAbdhWKI-s1aEUD8,4275
|
17
|
+
usso-0.24.12.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
18
|
+
usso-0.24.12.dist-info/entry_points.txt,sha256=4Zgpm5ELaAWPf0jPGJFz1_X69H7un8ycT3WdGoJ0Vvk,35
|
19
|
+
usso-0.24.12.dist-info/top_level.txt,sha256=g9Jf6h1Oyidh0vPiFni7UHInTJjSvu6cUalpLTIvthg,5
|
20
|
+
usso-0.24.12.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|