usso 0.24.18__py3-none-any.whl → 0.25.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/async_session.py CHANGED
@@ -2,7 +2,6 @@ from contextlib import asynccontextmanager
2
2
  from datetime import datetime, timedelta
3
3
 
4
4
  import aiohttp
5
- from fastapi import params
6
5
  import jwt
7
6
 
8
7
 
@@ -76,7 +75,7 @@ class AsyncUssoSession:
76
75
  if not self.access_token:
77
76
  # Get a new token if none exists or it has expired
78
77
  token_data = await self._refresh()
79
- self.access_token = token_data["access_token"]
78
+ self.access_token = token_data.get("access_token")
80
79
 
81
80
  # Update headers with the new access token
82
81
  if self.session:
usso/core.py CHANGED
@@ -4,8 +4,9 @@ import uuid
4
4
  from functools import lru_cache
5
5
  from typing import Optional, Tuple
6
6
 
7
+ import cachetools.func
7
8
  import jwt
8
- from pydantic import BaseModel
9
+ from pydantic import BaseModel, model_validator
9
10
  from singleton import Singleton
10
11
 
11
12
  from . import b64tools
@@ -16,12 +17,20 @@ logger = logging.getLogger("usso")
16
17
 
17
18
  class UserData(BaseModel):
18
19
  user_id: str
20
+ workspace_id: str | None = None
21
+ workspace_ids: list[str] = []
22
+ token_type: str = "access"
23
+
19
24
  email: str | None = None
20
25
  phone: str | None = None
26
+ username: str | None = None
27
+
21
28
  authentication_method: str | None = None
22
29
  is_active: bool = False
30
+
23
31
  jti: str | None = None
24
32
  data: dict | None = None
33
+
25
34
  token: str | None = None
26
35
 
27
36
  @property
@@ -40,74 +49,126 @@ class UserData(BaseModel):
40
49
  return b64tools.b64_encode_uuid_strip(self.uid)
41
50
 
42
51
 
52
+ def get_authorization_scheme_param(
53
+ authorization_header_value: str | None,
54
+ ) -> tuple[str, str]:
55
+ if not authorization_header_value:
56
+ return "", ""
57
+ scheme, _, param = authorization_header_value.partition(" ")
58
+ return scheme, param
59
+
60
+
61
+ def decode_token(key, token: str, algorithms=["RS256"], **kwargs) -> dict:
62
+ try:
63
+ decoded = jwt.decode(token, key, algorithms=algorithms)
64
+ decoded["token"] = token
65
+ return UserData(**decoded)
66
+ except jwt.exceptions.ExpiredSignatureError:
67
+ if kwargs.get("raise_exception", True):
68
+ raise USSOException(status_code=401, error="expired_signature")
69
+ except jwt.exceptions.InvalidSignatureError:
70
+ if kwargs.get("raise_exception", True):
71
+ raise USSOException(status_code=401, error="invalid_signature")
72
+ except jwt.exceptions.InvalidAlgorithmError:
73
+ if kwargs.get("raise_exception", True):
74
+ raise USSOException(status_code=401, error="invalid_algorithm")
75
+ except jwt.exceptions.InvalidIssuedAtError:
76
+ if kwargs.get("raise_exception", True):
77
+ raise USSOException(status_code=401, error="invalid_issued_at")
78
+ except jwt.exceptions.InvalidTokenError:
79
+ if kwargs.get("raise_exception", True):
80
+ raise USSOException(status_code=401, error="invalid_token")
81
+ except jwt.exceptions.InvalidKeyError:
82
+ if kwargs.get("raise_exception", True):
83
+ raise USSOException(status_code=401, error="invalid_key")
84
+ except USSOException as e:
85
+ if kwargs.get("raise_exception", True):
86
+ raise e
87
+ except Exception as e:
88
+ if kwargs.get("raise_exception", True):
89
+ raise USSOException(status_code=401, error="error", message=str(e))
90
+ logger.error(e)
91
+
92
+
93
+ @lru_cache
94
+ def get_jwk_keys(jwk_url: str) -> jwt.PyJWKClient:
95
+ return jwt.PyJWKClient(jwk_url, headers={"User-Agent": "usso-python"})
96
+
97
+
98
+ def decode_token_jwk(jwk_url: str, token: str, **kwargs) -> UserData | None:
99
+ """Return the user associated with a token value."""
100
+ try:
101
+ jwk_client = get_jwk_keys(jwk_url)
102
+ signing_key = jwk_client.get_signing_key_from_jwt(token)
103
+ return decode_token(signing_key.key, token, **kwargs)
104
+ except USSOException as e:
105
+ if kwargs.get("raise_exception", True):
106
+ raise e
107
+ logger.error(e)
108
+ except Exception as e:
109
+ if kwargs.get("raise_exception", True):
110
+ raise USSOException(
111
+ status_code=401,
112
+ error="error",
113
+ message=str(e),
114
+ )
115
+ logger.error(e)
116
+
117
+
118
+ class JWTConfig(BaseModel):
119
+ jwk_url: str | None = None
120
+ secret: str | None = None
121
+ type: str = "RS256"
122
+ header: dict[str, str] = {"type": "Cookie", "name": "usso_access_token"}
123
+
124
+ def __hash__(self):
125
+ return hash(self.model_dump_json())
126
+
127
+ @model_validator(mode="before")
128
+ def validate_secret(cls, data: dict):
129
+ if not data.get("jwk_url") and not data.get("secret"):
130
+ raise ValueError("Either jwk_url or secret must be provided")
131
+ return data
132
+
133
+ @classmethod
134
+ @cachetools.func.ttl_cache(maxsize=128, ttl=10 * 60)
135
+ def get_jwk_keys(cls, jwk_url):
136
+ return get_jwk_keys(jwk_url)
137
+
138
+ @cachetools.func.ttl_cache(maxsize=128, ttl=10 * 60)
139
+ def decode(self, token: str):
140
+ if self.jwk_url:
141
+ return decode_token_jwk(self.jwk_url, token)
142
+ return decode_token(self.secret, token, algorithms=[self.type])
143
+
144
+
43
145
  class Usso(metaclass=Singleton):
44
146
  def __init__(self, jwks_url: str | None = None):
45
147
  if jwks_url is None:
46
148
  jwks_url = os.getenv("USSO_JWKS_URL")
47
149
  self.jwks_url = jwks_url
48
150
 
49
- @lru_cache
50
- def get_jwks_keys(self):
51
- return jwt.PyJWKClient(
52
- self.jwks_url,
53
- headers={
54
- "User-Agent": "usso-python",
55
- },
56
- )
151
+ def get_jwk_keys(self):
152
+ return get_jwk_keys(self.jwks_url)
57
153
 
58
154
  def get_authorization_scheme_param(
59
- self,
60
- authorization_header_value: Optional[str],
155
+ self, authorization_header_value: Optional[str]
61
156
  ) -> Tuple[str, str]:
62
- if not authorization_header_value:
63
- return "", ""
64
- scheme, _, param = authorization_header_value.partition(" ")
65
- return scheme, param
66
-
67
- def decode_token(self, key, token: str, **kwargs) -> dict:
68
- try:
69
- decoded = jwt.decode(token, key, algorithms=["RS256"])
70
- if decoded["token_type"] != "access":
71
- raise USSOException(status_code=401, error="invalid_token_type")
72
- decoded["token"] = token
73
- return UserData(**decoded)
74
- except jwt.exceptions.ExpiredSignatureError:
75
- if kwargs.get("raise_exception", True):
76
- raise USSOException(status_code=401, error="expired_signature")
77
- except jwt.exceptions.InvalidSignatureError:
78
- if kwargs.get("raise_exception", True):
79
- raise USSOException(status_code=401, error="invalid_signature")
80
- except jwt.exceptions.InvalidAlgorithmError:
81
- if kwargs.get("raise_exception", True):
82
- raise USSOException(status_code=401, error="invalid_algorithm")
83
- except jwt.exceptions.InvalidIssuedAtError:
84
- if kwargs.get("raise_exception", True):
85
- raise USSOException(status_code=401, error="invalid_issued_at")
86
- except jwt.exceptions.InvalidTokenError:
87
- if kwargs.get("raise_exception", True):
88
- raise USSOException(status_code=401, error="invalid_token")
89
- except jwt.exceptions.InvalidKeyError:
90
- if kwargs.get("raise_exception", True):
91
- raise USSOException(status_code=401, error="invalid_key")
92
- except USSOException as e:
93
- if kwargs.get("raise_exception", True):
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)
157
+ return get_authorization_scheme_param(authorization_header_value)
99
158
 
100
159
  def user_data_from_token(self, token: str, **kwargs) -> UserData | None:
101
160
  """Return the user associated with a token value."""
161
+ user_data = decode_token_jwk(self.jwks_url, token, **kwargs)
162
+ if user_data.token_type.lower() != kwargs.get("token_type", "access"):
163
+ raise USSOException(status_code=401, error="invalid_token_type")
164
+ return user_data
165
+
166
+ def user_data_from_token_none(self, token: str, **kwargs) -> UserData | None:
102
167
  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)
106
- except Exception as e:
107
- if kwargs.get("raise_exception", True):
108
- raise USSOException(
109
- status_code=401,
110
- error="error",
111
- message=str(e),
112
- )
113
- logger.error(e)
168
+ return self.user_data_from_token(token, **kwargs)
169
+ except USSOException:
170
+ # logger.error(str(e))
171
+ return None
172
+ except Exception:
173
+ # logger.error(str(e))
174
+ return None
@@ -2,160 +2,67 @@ import json
2
2
  import logging
3
3
  import os
4
4
 
5
- import cachetools.func
6
- import jwt
7
5
  from fastapi import Request, WebSocket
8
- from pydantic import BaseModel, model_validator
9
6
  from starlette.status import HTTP_401_UNAUTHORIZED
10
7
 
11
- from usso.core import UserData
12
8
  from usso.exceptions import USSOException
13
9
 
14
- logger = logging.getLogger("usso")
15
-
16
-
17
- class JWTConfig(BaseModel):
18
- jwk_url: str | None = None
19
- secret: str | None = None
20
- type: str = "RS256"
21
- header: dict[str, str] = {"type": "Cookie", "name": "usso_access_token"}
22
-
23
- def __hash__(self):
24
- return hash(self.model_dump_json())
25
-
26
- @model_validator(mode="before")
27
- def validate_secret(cls, data: dict):
28
- if not data.get("jwk_url") and not data.get("secret"):
29
- raise ValueError("Either jwk_url or secret must be provided")
30
- return data
10
+ from ..core import JWTConfig, UserData
11
+ from .integration import get_request_token
31
12
 
32
- @classmethod
33
- @cachetools.func.ttl_cache(maxsize=128, ttl=10 * 60)
34
- def get_jwk_keys(cls, jwk_url):
35
- return jwt.PyJWKClient(
36
- jwk_url,
37
- headers={
38
- "User-Agent": "usso-python",
39
- },
40
- )
41
-
42
- @cachetools.func.ttl_cache(maxsize=128, ttl=10 * 60)
43
- def decode(self, token: str):
44
- if self.jwk_url:
45
- jwk_client = self.get_jwk_keys(self.jwk_url)
46
- signing_key = jwk_client.get_signing_key_from_jwt(token)
47
- return jwt.decode(token, signing_key.key, algorithms=[self.type])
48
-
49
- return jwt.decode(token, self.secret, algorithms=[self.type])
13
+ logger = logging.getLogger("usso")
50
14
 
51
15
 
52
16
  class Usso:
53
17
 
54
- def __init__(self, jwt_config: str | dict | JWTConfig | None = None):
18
+ def __init__(
19
+ self,
20
+ jwt_config: (
21
+ str | dict | JWTConfig | list[str] | list[dict] | list[JWTConfig] | None
22
+ ) = None,
23
+ ):
55
24
  if jwt_config is None:
56
25
  self.jwk_url = os.getenv("USSO_JWK_URL")
26
+ self.jwt_configs = [JWTConfig(jwk_url=self.jwk_url)]
57
27
  return
58
28
 
59
- if isinstance(jwt_config, str):
60
- jwt_config = json.loads(jwt_config)
61
- if isinstance(jwt_config, dict):
62
- jwt_config = JWTConfig(**jwt_config)
29
+ def _get_config(jwt_config):
30
+ if isinstance(jwt_config, str):
31
+ jwt_config = json.loads(jwt_config)
32
+ if isinstance(jwt_config, dict):
33
+ jwt_config = JWTConfig(**jwt_config)
34
+ return jwt_config
63
35
 
64
- self.jwk_url = jwt_config
65
- self.jwt_config = jwt_config
36
+ if isinstance(jwt_config, str | dict | JWTConfig):
37
+ jwt_config = [_get_config(jwt_config)]
38
+ elif isinstance(jwt_config, list):
39
+ jwt_config = [_get_config(j) for j in jwt_config]
66
40
 
67
- def get_authorization_scheme_param(
68
- self,
69
- authorization_header_value: str | None,
70
- ) -> tuple[str, str]:
71
- if not authorization_header_value:
72
- return "", ""
73
- scheme, _, param = authorization_header_value.partition(" ")
74
- return scheme, param
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)
41
+ # self.jwk_url = jwt_config
42
+ self.jwt_configs = jwt_config
108
43
 
109
44
  def user_data_from_token(self, token: str, **kwargs) -> UserData | None:
110
45
  """Return the user associated with a token value."""
111
- try:
112
- decoded = self.jwk_url.decode(token)
113
- if decoded["token_type"] != "access":
114
- raise USSOException(status_code=401, error="invalid_token_type")
115
- decoded["token"] = token
116
- return UserData(**decoded)
117
- except jwt.exceptions.ExpiredSignatureError:
118
- if kwargs.get("raise_exception", True):
119
- raise USSOException(status_code=401, error="expired_signature")
120
- except jwt.exceptions.InvalidSignatureError:
121
- if kwargs.get("raise_exception", True):
122
- raise USSOException(status_code=401, error="invalid_signature")
123
- except jwt.exceptions.InvalidAlgorithmError:
124
- if kwargs.get("raise_exception", True):
125
- raise USSOException(status_code=401, error="invalid_algorithm")
126
- except jwt.exceptions.InvalidIssuedAtError:
127
- if kwargs.get("raise_exception", True):
128
- raise USSOException(status_code=401, error="invalid_issued_at")
129
- except jwt.exceptions.InvalidTokenError:
130
- if kwargs.get("raise_exception", True):
131
- raise USSOException(status_code=401, error="invalid_token")
132
- except jwt.exceptions.InvalidKeyError:
133
- if kwargs.get("raise_exception", True):
134
- raise USSOException(status_code=401, error="invalid_key")
135
- except KeyError as e:
136
- if kwargs.get("raise_exception", True):
137
- raise USSOException(status_code=401, error="key_error", message=str(e))
138
- except USSOException as e:
139
- if kwargs.get("raise_exception", True):
140
- raise e
141
- except Exception as e:
142
- if kwargs.get("raise_exception", True):
143
- raise USSOException(status_code=401, error="error", message=str(e))
144
- logger.error(e)
145
-
146
- async def jwt_access_security(self, request: Request) -> UserData | None:
46
+ exp = None
47
+ for jwk_config in self.jwt_configs:
48
+ try:
49
+ return jwk_config.decode(token)
50
+ except USSOException as e:
51
+ exp = e
52
+
53
+ if kwargs.get("raise_exception", True):
54
+ if exp:
55
+ raise exp
56
+ raise USSOException(
57
+ status_code=HTTP_401_UNAUTHORIZED,
58
+ error="unauthorized",
59
+ )
60
+
61
+ async def jwt_access_security(self, request: Request, **kwargs) -> UserData | None:
147
62
  """Return the user associated with a token value."""
148
- kwargs = {}
149
- authorization = request.headers.get("Authorization")
150
- if authorization:
151
- scheme, credentials = self.get_authorization_scheme_param(authorization)
152
- if scheme.lower() == "bearer":
153
- token = credentials
154
- return self.user_data_from_token(token, **kwargs)
155
-
156
- cookie_token = request.cookies.get("usso_access_token")
157
- if cookie_token:
158
- return self.user_data_from_token(cookie_token, **kwargs)
63
+ token = get_request_token(request)
64
+ if token:
65
+ return self.user_data_from_token(token)
159
66
 
160
67
  if kwargs.get("raise_exception", True):
161
68
  raise USSOException(
@@ -164,19 +71,13 @@ class Usso:
164
71
  )
165
72
  return None
166
73
 
167
- async def jwt_access_security_ws(self, websocket: WebSocket) -> UserData | None:
74
+ async def jwt_access_security_ws(
75
+ self, websocket: WebSocket, **kwargs
76
+ ) -> UserData | None:
168
77
  """Return the user associated with a token value."""
169
- kwargs = {}
170
- authorization = websocket.headers.get("Authorization")
171
- if authorization:
172
- scheme, credentials = self.get_authorization_scheme_param(authorization)
173
- if scheme.lower() == "bearer":
174
- token = credentials
175
- return self.user_data_from_token(token, **kwargs)
176
-
177
- cookie_token = websocket.cookies.get("usso_access_token")
178
- if cookie_token:
179
- return self.user_data_from_token(cookie_token, **kwargs)
78
+ token = get_request_token(websocket)
79
+ if token:
80
+ return self.user_data_from_token(token)
180
81
 
181
82
  if kwargs.get("raise_exception", True):
182
83
  raise USSOException(
usso/session.py CHANGED
@@ -69,7 +69,7 @@ class UssoSession:
69
69
  if exp < datetime.now():
70
70
  self.access_token = None
71
71
  if not self.access_token:
72
- self.access_token = self._refresh()["access_token"]
72
+ self.access_token = self._refresh().get("access_token")
73
73
  self.session.headers.update(
74
74
  {"Authorization": f"Bearer {self.access_token}"}
75
75
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: usso
3
- Version: 0.24.18
3
+ Version: 0.25.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>
@@ -42,7 +42,6 @@ Classifier: Programming Language :: Python :: 3 :: Only
42
42
  Requires-Python: >=3.9
43
43
  Description-Content-Type: text/markdown
44
44
  License-File: LICENSE.txt
45
- Requires-Dist: peppercorn
46
45
  Requires-Dist: pydantic >=2
47
46
  Requires-Dist: requests >=2.26.0
48
47
  Requires-Dist: pyjwt[crypto]
@@ -0,0 +1,20 @@
1
+ usso/__init__.py,sha256=NnOS_S1a-JKTOlGe1nw-kCL3m0y82mA2mDraus7BQ2o,120
2
+ usso/api.py,sha256=xlDq2nZNpq3mhAvqIbGEfANHNjJpPquSeULBfS7iMJw,5094
3
+ usso/async_api.py,sha256=rb-Xh5oudmZrPYM_iH_B75b5Z0Fvi1V1uurdcKE51w0,5551
4
+ usso/async_session.py,sha256=nFIrtV3Tp0H-s2ZkMLU9_fVSeVGq1EtY1bGT_XOS5Vw,4336
5
+ usso/b64tools.py,sha256=HGQ0E59vzjrQo2-4jrcY03ebtTaYwTtCZ7KgJaEmxO0,610
6
+ usso/core.py,sha256=bWegFuGsWMmfz1b0upGPn5E8X3az4IOuJ-WqzRDMngM,5767
7
+ usso/exceptions.py,sha256=hawOAuVbvQtjgRfwp1KFZ4SmV7fh720y5Gom9JVA8W8,504
8
+ usso/package_data.dat,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ usso/session.py,sha256=Lky2O8FGbOMJFOMxxdE0rhpgwWKThGQfr-X9YQsFpLk,2358
10
+ usso/django/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ usso/django/middleware.py,sha256=EEEpHvMQ6QiWw2HY8zQ2Aec0RCATcLWsCKeyiPWJKio,3245
12
+ usso/fastapi/__init__.py,sha256=0EcdOzb4f3yu9nILIdGWnlyUz-0VaVX2az1e3f2BusI,201
13
+ usso/fastapi/auth_middleware.py,sha256=HfRbdelAQ4URwTA8hEyeq0IYBEZcbRa-utEHf5rRw_s,2710
14
+ usso/fastapi/integration.py,sha256=VAUWaa7ChQ1jTtn8A136VgyG6t2kDo5pGK-3RgmNDVs,1669
15
+ usso-0.25.0.dist-info/LICENSE.txt,sha256=ceC9ZJOV9H6CtQDcYmHOS46NA3dHJ_WD4J9blH513pc,1081
16
+ usso-0.25.0.dist-info/METADATA,sha256=3_BvP1GtgbIGMng5NDF64x3zlcviiD0VHMiuxGGllt8,4248
17
+ usso-0.25.0.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
18
+ usso-0.25.0.dist-info/entry_points.txt,sha256=4Zgpm5ELaAWPf0jPGJFz1_X69H7un8ycT3WdGoJ0Vvk,35
19
+ usso-0.25.0.dist-info/top_level.txt,sha256=g9Jf6h1Oyidh0vPiFni7UHInTJjSvu6cUalpLTIvthg,5
20
+ usso-0.25.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,20 +0,0 @@
1
- usso/__init__.py,sha256=NnOS_S1a-JKTOlGe1nw-kCL3m0y82mA2mDraus7BQ2o,120
2
- usso/api.py,sha256=xlDq2nZNpq3mhAvqIbGEfANHNjJpPquSeULBfS7iMJw,5094
3
- usso/async_api.py,sha256=rb-Xh5oudmZrPYM_iH_B75b5Z0Fvi1V1uurdcKE51w0,5551
4
- usso/async_session.py,sha256=uMLrcNC2p7sT5HMD5G3rA3HelQWzN7ZM2OGTqZuzTLk,4359
5
- usso/b64tools.py,sha256=HGQ0E59vzjrQo2-4jrcY03ebtTaYwTtCZ7KgJaEmxO0,610
6
- usso/core.py,sha256=cOpETK_gGVsUJT0EeIebOGLEbF8vHVET-_I-8QxOCyE,3977
7
- usso/exceptions.py,sha256=hawOAuVbvQtjgRfwp1KFZ4SmV7fh720y5Gom9JVA8W8,504
8
- usso/package_data.dat,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- usso/session.py,sha256=rBR_Obitvf78ulu5yJ1lug6x_1JBn6wfKARle5nvx2E,2354
10
- usso/django/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- usso/django/middleware.py,sha256=EEEpHvMQ6QiWw2HY8zQ2Aec0RCATcLWsCKeyiPWJKio,3245
12
- usso/fastapi/__init__.py,sha256=0EcdOzb4f3yu9nILIdGWnlyUz-0VaVX2az1e3f2BusI,201
13
- usso/fastapi/auth_middleware.py,sha256=DYrNPy_9FIV1amRuafoJtgGMi8uE0FPmSKBUGP79GNo,7616
14
- usso/fastapi/integration.py,sha256=VAUWaa7ChQ1jTtn8A136VgyG6t2kDo5pGK-3RgmNDVs,1669
15
- usso-0.24.18.dist-info/LICENSE.txt,sha256=ceC9ZJOV9H6CtQDcYmHOS46NA3dHJ_WD4J9blH513pc,1081
16
- usso-0.24.18.dist-info/METADATA,sha256=ss3VYoitAgs8EIdE36U3stypWvEGg-dSF6SeeJfDAxY,4275
17
- usso-0.24.18.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
18
- usso-0.24.18.dist-info/entry_points.txt,sha256=4Zgpm5ELaAWPf0jPGJFz1_X69H7un8ycT3WdGoJ0Vvk,35
19
- usso-0.24.18.dist-info/top_level.txt,sha256=g9Jf6h1Oyidh0vPiFni7UHInTJjSvu6cUalpLTIvthg,5
20
- usso-0.24.18.dist-info/RECORD,,