pypomes-jwt 0.4.5__tar.gz → 0.4.7__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.

Potentially problematic release.


This version of pypomes-jwt might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pypomes_jwt
3
- Version: 0.4.5
3
+ Version: 0.4.7
4
4
  Summary: A collection of Python pomes, penyeach (JWT module)
5
5
  Project-URL: Homepage, https://github.com/TheWiseCoder/PyPomes-JWT
6
6
  Project-URL: Bug Tracker, https://github.com/TheWiseCoder/PyPomes-JWT/issues
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "pypomes_jwt"
9
- version = "0.4.5"
9
+ version = "0.4.7"
10
10
  authors = [
11
11
  { name="GT Nunes", email="wisecoder01@gmail.com" }
12
12
  ]
@@ -68,6 +68,9 @@ class JwtData:
68
68
  """
69
69
  Add to storage the parameters needed to obtain and validate JWT tokens.
70
70
 
71
+ Protocol indication in *service_url* (typically *http:* or *https:*), is disregarded, to guarantee
72
+ that processing herein will not be affected by in-transit protocol changes.
73
+
71
74
  Presently, the *refresh_max_age* data is not relevant, as the authorization parameters in *claims*
72
75
  (typically, an acess-key/secret-key pair), have been previously validated elsewhere.
73
76
  This situation might change in the future.
@@ -84,8 +87,9 @@ class JwtData:
84
87
  :param local_provider: whether 'service_url' is a local endpoint
85
88
  :param logger: optional logger
86
89
  """
87
- # obtain the item in s"torage
88
- item_data: dict[str, dict[str, Any]] = self.retrieve_access_data(service_url=service_url)
90
+ # obtain the item in storage
91
+ item_data: dict[str, dict[str, Any]] = self.retrieve_access_data(service_url=service_url,
92
+ logger=logger)
89
93
  if not item_data:
90
94
  # build control data
91
95
  control_data: dict[str, Any] = {
@@ -122,9 +126,9 @@ class JwtData:
122
126
  with self.access_lock:
123
127
  self.access_data.append(item_data)
124
128
  if logger:
125
- logger.debug(f"JWT token data added to storage for '{service_url}'")
129
+ logger.debug(f"JWT data added for '{service_url}': {item_data}")
126
130
  elif logger:
127
- logger.warning(f"JWT token data already exists for '{service_url}'")
131
+ logger.warning(f"JWT data already exists for '{service_url}'")
128
132
 
129
133
  def remove_access_data(self,
130
134
  service_url: str,
@@ -136,33 +140,15 @@ class JwtData:
136
140
  :param logger: optional logger
137
141
  """
138
142
  # obtain the item in storage
139
- item_data: dict[str, dict[str, Any]] = self.retrieve_access_data(service_url=service_url)
143
+ item_data: dict[str, dict[str, Any]] = self.retrieve_access_data(service_url=service_url,
144
+ logger=logger)
140
145
  if item_data:
141
146
  with self.access_lock:
142
147
  self.access_data.remove(item_data)
143
148
  if logger:
144
- logger.debug(f"Removed access data for '{service_url}'")
149
+ logger.debug(f"Removed JWT data for '{service_url}'")
145
150
  elif logger:
146
- logger.warning(f"No access data found for '{service_url}'")
147
-
148
- def retrieve_access_data(self,
149
- service_url: str) -> dict[str, dict[str, Any]]:
150
- """
151
- Retrieve and return the access data in storage corresponding to the given parameters.
152
-
153
- :param service_url: the reference URL for obtaining JWT tokens
154
- :return: the corresponding item in storage, or 'None' if not found
155
- """
156
- # initialize the return variable
157
- result: dict[str, dict[str, Any]] | None = None
158
-
159
- with self.access_lock:
160
- for item_data in self.access_data:
161
- if service_url == item_data.get("control-data").get("service-url"):
162
- result = item_data
163
- break
164
-
165
- return result
151
+ logger.warning(f"No JWT data found for '{service_url}'")
166
152
 
167
153
  def get_token_data(self,
168
154
  service_url: str,
@@ -196,7 +182,8 @@ class JwtData:
196
182
  result: dict[str, Any]
197
183
 
198
184
  # obtain the item in storage
199
- item_data: dict[str, Any] = self.retrieve_access_data(service_url=service_url)
185
+ item_data: dict[str, Any] = self.retrieve_access_data(service_url=service_url,
186
+ logger=logger)
200
187
  # was the JWT data obtained ?
201
188
  if item_data:
202
189
  # yes, proceed
@@ -250,7 +237,7 @@ class JwtData:
250
237
  }
251
238
  else:
252
239
  # JWT data not found
253
- err_msg: str = f"No access data found for {service_url}"
240
+ err_msg: str = f"No JWT data found for {service_url}"
254
241
  if logger:
255
242
  logger.error(err_msg)
256
243
  raise RuntimeError(err_msg)
@@ -258,11 +245,13 @@ class JwtData:
258
245
  return result
259
246
 
260
247
  def get_token_claims(self,
261
- token: str) -> dict[str, Any]:
248
+ token: str,
249
+ logger: Logger = None) -> dict[str, Any]:
262
250
  """
263
251
  Obtain and return the claims of a JWT *token*.
264
252
 
265
253
  :param token: the token to be inspected for claims
254
+ :param logger: optional logger
266
255
  :return: the token's claimset, or 'None' if error
267
256
  :raises InvalidTokenError: token is not valid
268
257
  :raises ExpiredSignatureError: token has expired
@@ -278,11 +267,50 @@ class JwtData:
278
267
  break
279
268
 
280
269
  if not algorithm or not key:
281
- raise InvalidTokenError("Token is not valid")
270
+ raise InvalidTokenError("JWT token is not valid")
282
271
 
283
- return jwt.decode(jwt=token,
284
- key=key,
285
- algorithms=[algorithm])
272
+ if logger:
273
+ logger.debug(msg=f"Retrieve claims for JWT token '{token}'")
274
+ result: dict[str, Any] = jwt.decode(jwt=token,
275
+ key=key,
276
+ algorithms=[algorithm])
277
+ if logger:
278
+ logger.debug(f"Retrieved claims for JWT token '{token}': {result}")
279
+
280
+ return result
281
+
282
+ def retrieve_access_data(self,
283
+ service_url: str,
284
+ logger: Logger = None) -> dict[str, dict[str, Any]]:
285
+ """
286
+ Retrieve and return the access data in storage corresponding to *service_url*.
287
+
288
+ Protocol indication in *service_url* (typically *http:* or *https:*), is disregarded, to guarantee
289
+ that processing herein will not be affected by in-transit protocol changes.
290
+
291
+ :param service_url: the reference URL for obtaining JWT tokens
292
+ :param logger: optional logger
293
+ :return: the corresponding item in storage, or 'None' if not found
294
+ """
295
+ # initialize the return variable
296
+ result: dict[str, dict[str, Any]] | None = None
297
+
298
+ # disregard protocol
299
+ if service_url.find("://") > 0:
300
+ service_url = service_url[service_url.index("://")+3:]
301
+
302
+ with self.access_lock:
303
+ for item_data in self.access_data:
304
+ item_url: str = item_data.get("control-data").get("service-url")
305
+ if item_url.find("://") > 0:
306
+ item_url = item_url[item_url.index("://")+3:]
307
+ if service_url == item_url:
308
+ result = item_data
309
+ break
310
+ if logger:
311
+ logger.debug(f"JWT data for '{service_url}': {result}")
312
+
313
+ return result
286
314
 
287
315
 
288
316
  def jwt_request_token(errors: list[str],
@@ -312,7 +340,7 @@ def jwt_request_token(errors: list[str],
312
340
 
313
341
  # request the JWT token
314
342
  if logger:
315
- logger.debug(f"POST requesting JWT token to {service_url}")
343
+ logger.debug(f"POST request JWT token to '{service_url}'")
316
344
  response: Response = requests.post(
317
345
  url=service_url,
318
346
  json=claims,
@@ -324,7 +352,7 @@ def jwt_request_token(errors: list[str],
324
352
  # yes, save the access token data returned
325
353
  result = response.json()
326
354
  if logger:
327
- logger.debug(f"Access token obtained: {result}")
355
+ logger.debug(f"JWT token obtained: {result}")
328
356
  else:
329
357
  # no, report the problem
330
358
  err_msg: str = f"POST request of '{service_url}' failed: {response.reason}"
@@ -339,7 +367,8 @@ def jwt_request_token(errors: list[str],
339
367
 
340
368
  def jwt_validate_token(token: str,
341
369
  key: bytes | str,
342
- algorithm: str) -> None:
370
+ algorithm: str,
371
+ logger: Logger = None) -> None:
343
372
  """
344
373
  Verify if *token* ia a valid JWT token.
345
374
 
@@ -348,11 +377,14 @@ def jwt_validate_token(token: str,
348
377
  :param token: the token to be validated
349
378
  :param key: the secret or public key used to create the token (HS or RSA authentication, respectively)
350
379
  :param algorithm: the algorithm used to to sign the token with
380
+ :param logger: optional logger
351
381
  :raises InvalidTokenError: token is invalid
352
382
  :raises InvalidKeyError: authentication key is not in the proper format
353
383
  :raises ExpiredSignatureError: token and refresh period have expired
354
384
  :raises InvalidSignatureError: signature does not match the one provided as part of the token
355
385
  """
386
+ if logger:
387
+ logger.debug(msg=f"Verify request for JWT token '{token}'")
356
388
  jwt.decode(jwt=token,
357
389
  key=key,
358
390
  algorithms=[algorithm])
@@ -44,6 +44,9 @@ def jwt_set_service_access(service_url: str,
44
44
  """
45
45
  Set the data needed to obtain JWT tokens from *service_url*.
46
46
 
47
+ Protocol indication in *service_url* (typically *http:* or *https:*), is disregarded, to guarantee
48
+ that processing herein will not be affected by in-transit protocol changes.
49
+
47
50
  :param service_url: the reference URL
48
51
  :param claims: the JWT claimset, as key-value pairs
49
52
  :param algorithm: the authentication type
File without changes
File without changes
File without changes
File without changes