usso 0.12.0__py3-none-any.whl → 0.14.0__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/__init__.py +1 -1
- usso/core.py +49 -0
- usso/fastapi/__init__.py +1 -1
- usso/fastapi/integration.py +7 -55
- {usso-0.12.0.dist-info → usso-0.14.0.dist-info}/METADATA +1 -1
- usso-0.14.0.dist-info/RECORD +13 -0
- usso-0.12.0.dist-info/RECORD +0 -13
- {usso-0.12.0.dist-info → usso-0.14.0.dist-info}/LICENSE.txt +0 -0
- {usso-0.12.0.dist-info → usso-0.14.0.dist-info}/WHEEL +0 -0
- {usso-0.12.0.dist-info → usso-0.14.0.dist-info}/entry_points.txt +0 -0
- {usso-0.12.0.dist-info → usso-0.14.0.dist-info}/top_level.txt +0 -0
usso/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
from .core import UserData
|
1
|
+
from .core import UserData, user_data_from_token
|
usso/core.py
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import os
|
2
|
+
import logging
|
1
3
|
import uuid
|
2
4
|
from functools import lru_cache
|
3
5
|
from typing import Optional, Tuple
|
@@ -6,6 +8,9 @@ import jwt
|
|
6
8
|
from pydantic import BaseModel
|
7
9
|
|
8
10
|
from . import b64tools
|
11
|
+
from .exceptions import USSOException
|
12
|
+
|
13
|
+
logger = logging.getLogger("usso")
|
9
14
|
|
10
15
|
|
11
16
|
class UserData(BaseModel):
|
@@ -43,6 +48,50 @@ def get_authorization_scheme_param(
|
|
43
48
|
return scheme, param
|
44
49
|
|
45
50
|
|
51
|
+
def user_data_from_token(token: str, **kwargs) -> UserData | None:
|
52
|
+
"""Return the user associated with a token value."""
|
53
|
+
try:
|
54
|
+
header = jwt.get_unverified_header(token)
|
55
|
+
jwks_url = header["jwk_url"]
|
56
|
+
assert os.getenv("USSO_JWKS_URL") == jwks_url
|
57
|
+
jwks_client = get_jwks_keys(jwks_url)
|
58
|
+
# , headers=optional_custom_headers)
|
59
|
+
signing_key = jwks_client.get_signing_key_from_jwt(token)
|
60
|
+
decoded = jwt.decode(
|
61
|
+
token,
|
62
|
+
signing_key.key,
|
63
|
+
algorithms=["RS256"],
|
64
|
+
)
|
65
|
+
decoded["token"] = token
|
66
|
+
|
67
|
+
except jwt.exceptions.ExpiredSignatureError:
|
68
|
+
if kwargs.get("raise_exception"):
|
69
|
+
raise USSOException(status_code=401, error="expired_signature")
|
70
|
+
return None
|
71
|
+
except jwt.exceptions.InvalidSignatureError:
|
72
|
+
if kwargs.get("raise_exception"):
|
73
|
+
raise USSOException(status_code=401, error="invalid_signature")
|
74
|
+
return None
|
75
|
+
except jwt.exceptions.InvalidTokenError:
|
76
|
+
if kwargs.get("raise_exception"):
|
77
|
+
raise USSOException(
|
78
|
+
status_code=401,
|
79
|
+
error="invalid_token",
|
80
|
+
)
|
81
|
+
return None
|
82
|
+
except Exception as e:
|
83
|
+
if kwargs.get("raise_exception"):
|
84
|
+
raise USSOException(
|
85
|
+
status_code=401,
|
86
|
+
error="error",
|
87
|
+
message=str(e),
|
88
|
+
)
|
89
|
+
logger.error(e)
|
90
|
+
return None
|
91
|
+
|
92
|
+
return UserData(**decoded)
|
93
|
+
|
94
|
+
|
46
95
|
@lru_cache
|
47
96
|
def get_jwks_keys(jwks_url):
|
48
97
|
return jwt.PyJWKClient(jwks_url)
|
usso/fastapi/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
from .integration import jwt_access_security
|
1
|
+
from .integration import jwt_access_security
|
usso/fastapi/integration.py
CHANGED
@@ -1,62 +1,14 @@
|
|
1
1
|
import logging
|
2
2
|
|
3
|
-
import jwt
|
4
3
|
from fastapi import Request, WebSocket
|
5
4
|
from starlette.status import HTTP_401_UNAUTHORIZED
|
6
5
|
|
7
|
-
from usso.core import UserData, get_authorization_scheme_param,
|
6
|
+
from usso.core import UserData, get_authorization_scheme_param, user_data_from_token
|
8
7
|
from usso.exceptions import USSOException
|
9
8
|
|
10
9
|
logger = logging.getLogger("usso")
|
11
10
|
|
12
11
|
|
13
|
-
async def user_data_from_token(token: str, **kwargs) -> UserData | None:
|
14
|
-
"""Return the user associated with a token value."""
|
15
|
-
try:
|
16
|
-
header = jwt.get_unverified_header(token)
|
17
|
-
jwks_url = header["jwk_url"]
|
18
|
-
jwks_client = get_jwks_keys(jwks_url)
|
19
|
-
# , headers=optional_custom_headers)
|
20
|
-
signing_key = jwks_client.get_signing_key_from_jwt(token)
|
21
|
-
decoded = jwt.decode(
|
22
|
-
token,
|
23
|
-
signing_key.key,
|
24
|
-
algorithms=["RS256"],
|
25
|
-
)
|
26
|
-
decoded["token"] = token
|
27
|
-
|
28
|
-
except jwt.exceptions.ExpiredSignatureError:
|
29
|
-
if kwargs.get("raise_exception"):
|
30
|
-
raise USSOException(
|
31
|
-
status_code=HTTP_401_UNAUTHORIZED, error="expired_signature"
|
32
|
-
)
|
33
|
-
return None
|
34
|
-
except jwt.exceptions.InvalidSignatureError:
|
35
|
-
if kwargs.get("raise_exception"):
|
36
|
-
raise USSOException(
|
37
|
-
status_code=HTTP_401_UNAUTHORIZED, error="invalid_signature"
|
38
|
-
)
|
39
|
-
return None
|
40
|
-
except jwt.exceptions.InvalidTokenError:
|
41
|
-
if kwargs.get("raise_exception"):
|
42
|
-
raise USSOException(
|
43
|
-
status_code=HTTP_401_UNAUTHORIZED,
|
44
|
-
error="invalid_token",
|
45
|
-
)
|
46
|
-
return None
|
47
|
-
except Exception as e:
|
48
|
-
if kwargs.get("raise_exception"):
|
49
|
-
raise USSOException(
|
50
|
-
status_code=HTTP_401_UNAUTHORIZED,
|
51
|
-
error="error",
|
52
|
-
message=str(e),
|
53
|
-
)
|
54
|
-
logger.error(e)
|
55
|
-
return None
|
56
|
-
|
57
|
-
return UserData(**decoded)
|
58
|
-
|
59
|
-
|
60
12
|
async def jwt_access_security(request: Request) -> UserData | None:
|
61
13
|
"""Return the user associated with a token value."""
|
62
14
|
kwargs = {}
|
@@ -65,11 +17,11 @@ async def jwt_access_security(request: Request) -> UserData | None:
|
|
65
17
|
scheme, _, credentials = get_authorization_scheme_param(authorization)
|
66
18
|
if scheme.lower() == "bearer":
|
67
19
|
token = credentials
|
68
|
-
return
|
20
|
+
return user_data_from_token(token, **kwargs)
|
69
21
|
|
70
|
-
cookie_token = request.cookies.get("
|
22
|
+
cookie_token = request.cookies.get("usso_access_token")
|
71
23
|
if cookie_token:
|
72
|
-
return
|
24
|
+
return user_data_from_token(cookie_token, **kwargs)
|
73
25
|
|
74
26
|
if kwargs.get("raise_exception", True):
|
75
27
|
raise USSOException(
|
@@ -87,11 +39,11 @@ async def jwt_access_security_ws(websocket: WebSocket) -> UserData | None:
|
|
87
39
|
scheme, _, credentials = get_authorization_scheme_param(authorization)
|
88
40
|
if scheme.lower() == "bearer":
|
89
41
|
token = credentials
|
90
|
-
return
|
42
|
+
return user_data_from_token(token, **kwargs)
|
91
43
|
|
92
|
-
cookie_token = websocket.cookies.get("
|
44
|
+
cookie_token = websocket.cookies.get("usso_access_token")
|
93
45
|
if cookie_token:
|
94
|
-
return
|
46
|
+
return user_data_from_token(cookie_token, **kwargs)
|
95
47
|
|
96
48
|
if kwargs.get("raise_exception", True):
|
97
49
|
raise USSOException(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: usso
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.14.0
|
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>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
usso/__init__.py,sha256=fluJnb9X2ECUnUA0lNNR2xHdn3uSI2RVErQiFlqbOiU,49
|
2
|
+
usso/b64tools.py,sha256=6YCBx2lLaYFdk36f064VNZ1RejJTHtmgxqq0eT1sCwQ,518
|
3
|
+
usso/core.py,sha256=eTzztT0Daxwl3b9VzPZSk1A-QQoGaCQdW2duK8FEWoo,2690
|
4
|
+
usso/exceptions.py,sha256=hawOAuVbvQtjgRfwp1KFZ4SmV7fh720y5Gom9JVA8W8,504
|
5
|
+
usso/package_data.dat,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
usso/fastapi/__init__.py,sha256=3hB0_Hq4LxfIL5NTI7SdC0jsFEICcBSTv6b9RuBWdxw,45
|
7
|
+
usso/fastapi/integration.py,sha256=DwQxLnj74tnOVyzHhmM380Gi-PX4EjWKt4Q-Le9wLXw,1785
|
8
|
+
usso-0.14.0.dist-info/LICENSE.txt,sha256=ceC9ZJOV9H6CtQDcYmHOS46NA3dHJ_WD4J9blH513pc,1081
|
9
|
+
usso-0.14.0.dist-info/METADATA,sha256=R9H7c6B39Zs3QLyu23i5i4yuQGc-VND7VYJIuCBrhL0,4306
|
10
|
+
usso-0.14.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
11
|
+
usso-0.14.0.dist-info/entry_points.txt,sha256=4Zgpm5ELaAWPf0jPGJFz1_X69H7un8ycT3WdGoJ0Vvk,35
|
12
|
+
usso-0.14.0.dist-info/top_level.txt,sha256=g9Jf6h1Oyidh0vPiFni7UHInTJjSvu6cUalpLTIvthg,5
|
13
|
+
usso-0.14.0.dist-info/RECORD,,
|
usso-0.12.0.dist-info/RECORD
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
usso/__init__.py,sha256=bHjlWFkwxHTNsC0g-aUqynQ8IrtXp1apELqCqsrynns,27
|
2
|
-
usso/b64tools.py,sha256=6YCBx2lLaYFdk36f064VNZ1RejJTHtmgxqq0eT1sCwQ,518
|
3
|
-
usso/core.py,sha256=dYV6Oq7IFpSHKRIhKpCvvWF_a1r7cTHL_p35uxQi2ec,1114
|
4
|
-
usso/exceptions.py,sha256=hawOAuVbvQtjgRfwp1KFZ4SmV7fh720y5Gom9JVA8W8,504
|
5
|
-
usso/package_data.dat,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
usso/fastapi/__init__.py,sha256=lp2o47nCG-vIobgEOKdEnnPBGizv5om7oPXjqe0R9qU,67
|
7
|
-
usso/fastapi/integration.py,sha256=qJhJDprAxB0kEWqqIYZgNuNFZr9tFWTavhP0Mu39D5M,3364
|
8
|
-
usso-0.12.0.dist-info/LICENSE.txt,sha256=ceC9ZJOV9H6CtQDcYmHOS46NA3dHJ_WD4J9blH513pc,1081
|
9
|
-
usso-0.12.0.dist-info/METADATA,sha256=22uKL_AMKi9buPK83amShqq4oBrMsJ-Wakf_kcXP7m8,4306
|
10
|
-
usso-0.12.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
11
|
-
usso-0.12.0.dist-info/entry_points.txt,sha256=4Zgpm5ELaAWPf0jPGJFz1_X69H7un8ycT3WdGoJ0Vvk,35
|
12
|
-
usso-0.12.0.dist-info/top_level.txt,sha256=g9Jf6h1Oyidh0vPiFni7UHInTJjSvu6cUalpLTIvthg,5
|
13
|
-
usso-0.12.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|