pypomes-jwt 1.2.6__py3-none-any.whl → 1.2.7__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.

Potentially problematic release.


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

pypomes_jwt/jwt_pomes.py CHANGED
@@ -54,8 +54,7 @@ def jwt_verify_request(request: Request) -> Response:
54
54
  if auth_header and auth_header.startswith("Bearer "):
55
55
  # yes, extract and validate the JWT access token
56
56
  token: str = auth_header.split(" ")[1]
57
- claims: dict[str, Any] = jwt_validate_token(errors=None,
58
- token=token,
57
+ claims: dict[str, Any] = jwt_validate_token(token=token,
59
58
  nature="A")
60
59
  if claims:
61
60
  login: str = request.values.get("login")
@@ -129,10 +128,10 @@ def jwt_remove_account(account_id: str,
129
128
  logger=logger)
130
129
 
131
130
 
132
- def jwt_validate_token(errors: list[str] | None,
133
- token: str,
131
+ def jwt_validate_token(token: str,
134
132
  nature: str = None,
135
133
  account_id: str = None,
134
+ errors: list[str] = None,
136
135
  logger: Logger = None) -> dict[str, Any] | None:
137
136
  """
138
137
  Verify if *token* is a valid JWT token.
@@ -147,10 +146,10 @@ def jwt_validate_token(errors: list[str] | None,
147
146
  On success, return the token's claims (*header* and *payload*), as documented in *jwt_get_claims()*
148
147
  On failure, *errors* will contain the reason(s) for rejecting *token*.
149
148
 
150
- :param errors: incidental error messages
151
149
  :param token: the token to be validated
152
150
  :param nature: prefix identifying the nature of locally issued tokens
153
151
  :param account_id: optionally, validate the token's account owner
152
+ :param errors: incidental error messages
154
153
  :param logger: optional logger
155
154
  :return: The token's claims (*header* and *payload*) if it is valid, *None* otherwise
156
155
  """
@@ -188,12 +187,12 @@ def jwt_validate_token(errors: list[str] | None,
188
187
  where_data: dict[str, Any] = {JwtDbConfig.COL_KID: int(token_kid[1:])}
189
188
  if account_id:
190
189
  where_data[JwtDbConfig.COL_ACCOUNT] = account_id
191
- recs: list[tuple[str]] = db_select(errors=op_errors,
192
- sel_stmt=f"SELECT {JwtDbConfig.COL_ALGORITHM}, "
190
+ recs: list[tuple[str]] = db_select(sel_stmt=f"SELECT {JwtDbConfig.COL_ALGORITHM}, "
193
191
  f"{JwtDbConfig.COL_DECODER} "
194
192
  f"FROM {JwtDbConfig.TABLE}",
195
193
  where_data=where_data,
196
194
  engine=DbEngine(JwtDbConfig.ENGINE),
195
+ errors=op_errors,
197
196
  logger=logger)
198
197
  if recs:
199
198
  token_alg = recs[0][0]
@@ -277,9 +276,9 @@ def jwt_revoke_token(errors: list[str] | None,
277
276
  logger.debug(msg=f"Revoking token of account '{account_id}'")
278
277
 
279
278
  op_errors: list[str] = []
280
- token_claims: dict[str, Any] = jwt_validate_token(errors=op_errors,
281
- token=token,
279
+ token_claims: dict[str, Any] = jwt_validate_token(token=token,
282
280
  account_id=account_id,
281
+ errors=op_errors,
283
282
  logger=logger)
284
283
  if not op_errors:
285
284
  token_kid: str = token_claims["header"].get("kid")
@@ -446,24 +445,23 @@ def jwt_refresh_tokens(errors: list[str] | None,
446
445
  # assert the refresh token
447
446
  if refresh_token:
448
447
  # is the refresh token valid ?
449
- token_claims: dict[str, Any] = jwt_validate_token(errors=op_errors,
450
- token=refresh_token,
448
+ token_claims: dict[str, Any] = jwt_validate_token(token=refresh_token,
451
449
  nature="R",
452
450
  account_id=account_id,
451
+ errors=op_errors,
453
452
  logger=logger)
454
453
  if token_claims:
455
454
  # yes, proceed
456
455
  token_kid: str = token_claims["header"].get("kid")
457
456
 
458
457
  # start the database transaction
459
- db_conn: Any = db_connect(errors=op_errors,
460
- autocommit=False,
458
+ db_conn: Any = db_connect(autocommit=False,
461
459
  engine=DbEngine(JwtDbConfig.ENGINE),
460
+ errors=op_errors,
462
461
  logger=logger)
463
462
  if db_conn:
464
463
  # delete current refresh token
465
- db_delete(errors=op_errors,
466
- delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
464
+ db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
467
465
  where_data={
468
466
  JwtDbConfig.COL_KID: int(token_kid[1:]),
469
467
  JwtDbConfig.COL_ACCOUNT: account_id
@@ -471,6 +469,7 @@ def jwt_refresh_tokens(errors: list[str] | None,
471
469
  engine=DbEngine(JwtDbConfig.ENGINE),
472
470
  connection=db_conn,
473
471
  committable=False,
472
+ errors=op_errors,
474
473
  logger=logger)
475
474
 
476
475
  # issue the token pair
@@ -492,12 +491,11 @@ def jwt_refresh_tokens(errors: list[str] | None,
492
491
 
493
492
  # wrap-up the transaction
494
493
  if op_errors:
495
- db_rollback(errors=op_errors,
496
- connection=db_conn,
494
+ db_rollback(connection=db_conn,
497
495
  logger=logger)
498
496
  else:
499
- db_commit(errors=op_errors,
500
- connection=db_conn,
497
+ db_commit(connection=db_conn,
498
+ errors=op_errors,
501
499
  logger=logger)
502
500
  else:
503
501
  # refresh token not found
@@ -512,8 +510,8 @@ def jwt_refresh_tokens(errors: list[str] | None,
512
510
  return result
513
511
 
514
512
 
515
- def jwt_get_claims(errors: list[str] | None,
516
- token: str,
513
+ def jwt_get_claims(token: str,
514
+ errors: list[str] = None,
517
515
  logger: Logger = None) -> dict[str, Any] | None:
518
516
  """
519
517
  Retrieve the claims set of a JWT *token*.
@@ -548,8 +546,8 @@ def jwt_get_claims(errors: list[str] | None,
548
546
  }
549
547
  }
550
548
 
551
- :param errors: incidental error messages
552
549
  :param token: the token to be inspected for claims
550
+ :param errors: incidental error messages
553
551
  :param logger: optional logger
554
552
  :return: the token's claimset, or *None* if error
555
553
  """
@@ -38,8 +38,8 @@ def provider_register(provider_id: str,
38
38
  HTTP Basic Authorization scheme, wherein the credentials are B64-encoded and send in the request headers.
39
39
 
40
40
  Optional constant key-value pairs (such as ['Content-Type', 'application/x-www-form-urlencoded']), to be
41
- added to the request headers, may be specified in *header_data*. Likewise, optional constant key-value pairs
42
- (such as ['grant-type', 'client_crdentials']), to be added to the request body, may be specified in *body_data*.
41
+ added to the request headers, may be specified in *headers_data*. Likewise, optional constant key-value pairs
42
+ (such as ['grant_type', 'client_credentials']), to be added to the request body, may be specified in *body_data*.
43
43
 
44
44
  :param provider_id: the provider's identification
45
45
  :param access_url: the url to request authentication tokens with
@@ -96,9 +96,12 @@ def provider_get_token(errors: list[str] | None,
96
96
  try:
97
97
  # typical return on a token request:
98
98
  # {
99
- # "expires_in": <number-of-seconds>,
100
99
  # "token_type": "bearer",
101
- # "access_token": <the-token>
100
+ # "access_token": <str>,
101
+ # "expires_in": <number-of-seconds>,
102
+ # optional data:
103
+ # "refresh_token": <str>,
104
+ # "refresh_expires_in": <nomber-of-seconds>
102
105
  # }
103
106
  response: Response = requests.post(url=url,
104
107
  data=body_data,
@@ -133,8 +133,7 @@ class JwtRegistry:
133
133
  account_data = self.access_registry.pop(account_id, None)
134
134
 
135
135
  # remove from database
136
- db_delete(errors=None,
137
- delete_stmt=f"DELETE FROM {JwtDbConfig}",
136
+ db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig}",
138
137
  where_data={JwtDbConfig.COL_ACCOUNT: account_id},
139
138
  engine=DbEngine(JwtDbConfig.ENGINE),
140
139
  logger=logger)
@@ -264,9 +263,9 @@ class JwtRegistry:
264
263
  headers={"kid": "R0"})
265
264
 
266
265
  # make sure to have a database connection
267
- curr_conn: Any = db_conn or db_connect(errors=errors,
268
- autocommit=False,
266
+ curr_conn: Any = db_conn or db_connect(autocommit=False,
269
267
  engine=DbEngine(JwtDbConfig.ENGINE),
268
+ errors=errors,
270
269
  logger=logger)
271
270
  if curr_conn:
272
271
  # persist the candidate token (may raise an exception)
@@ -280,24 +279,22 @@ class JwtRegistry:
280
279
  algorithm=JwtConfig.DEFAULT_ALGORITHM.value,
281
280
  headers={"kid": f"R{token_id}"})
282
281
  # persist it
283
- db_update(errors=errors,
284
- update_stmt=f"UPDATE {JwtDbConfig.TABLE}",
282
+ db_update(update_stmt=f"UPDATE {JwtDbConfig.TABLE}",
285
283
  update_data={JwtDbConfig.COL_TOKEN: refresh_token},
286
284
  where_data={JwtDbConfig.COL_KID: token_id},
287
285
  engine=DbEngine(JwtDbConfig.ENGINE),
288
286
  connection=curr_conn,
289
- committable=False,
287
+ errors=errors,
290
288
  logger=logger)
291
289
 
292
290
  # wrap-up the transaction
293
291
  if not db_conn:
294
292
  if errors:
295
- db_rollback(errors=errors,
296
- connection=curr_conn,
293
+ db_rollback(connection=curr_conn,
297
294
  logger=logger)
298
295
  else:
299
- db_commit(errors=errors,
300
- connection=curr_conn,
296
+ db_commit(connection=curr_conn,
297
+ errors=errors,
301
298
  logger=logger)
302
299
  if errors:
303
300
  raise RuntimeError("; ".join(errors))
@@ -340,7 +337,7 @@ class JwtRegistry:
340
337
  @staticmethod
341
338
  def jwt_persist_token(account_id: str,
342
339
  jwt_token: str,
343
- db_conn: Any,
340
+ db_conn: Any = None,
344
341
  logger: Logger = None) -> int:
345
342
  """
346
343
  Persist the given token, making sure that the account limit is complied with.
@@ -349,7 +346,9 @@ class JwtRegistry:
349
346
  If a token's expiration timestamp is in the past, it is removed from storage. If the maximum number
350
347
  of active tokens for *account_id* has been reached, the oldest active one is alse removed,
351
348
  to make room for the new *jwt_token*.
352
- The provided database connection *db_conn* indicates that this operation is part of a larger transaction.
349
+
350
+ If provided, *db_conn* indicates that this operation is part of a larger database transaction.
351
+ Otherwise, the database transaction's scope is limited to this operation.
353
352
 
354
353
  :param account_id: the account identification
355
354
  :param jwt_token: the JWT token to persist
@@ -364,19 +363,18 @@ class JwtRegistry:
364
363
  errors: list[str] = []
365
364
  # noinspection PyTypeChecker
366
365
  recs: list[tuple[int, str, str, str]] = \
367
- db_select(errors=errors,
368
- sel_stmt=f"SELECT {JwtDbConfig.COL_KID}, {JwtDbConfig.COL_TOKEN} "
366
+ db_select(sel_stmt=f"SELECT {JwtDbConfig.COL_KID}, {JwtDbConfig.COL_TOKEN} "
369
367
  f"FROM {JwtDbConfig.TABLE}",
370
368
  where_data={JwtDbConfig.COL_ACCOUNT: account_id},
371
369
  engine=DbEngine(JwtDbConfig.ENGINE),
372
370
  connection=db_conn,
373
- committable=False,
371
+ errors=errors,
374
372
  logger=logger)
375
373
  if errors:
376
374
  raise RuntimeError("; ".join(errors))
377
375
 
378
376
  if logger:
379
- logger.debug(msg=f"Read {len(recs)} token from storage for account '{account_id}'")
377
+ logger.debug(msg=f"Retrieved {len(recs)} tokens from storage for account '{account_id}'")
380
378
  # remove the expired tokens
381
379
  just_now: int = int(datetime.now(tz=UTC).timestamp())
382
380
  oldest_ts: int = sys.maxsize
@@ -385,8 +383,8 @@ class JwtRegistry:
385
383
  for rec in recs:
386
384
  token: str = rec[1]
387
385
  token_id: int = rec[0]
388
- token_payload: dict[str, Any] = (jwt_get_claims(errors=errors,
389
- token=token,
386
+ token_payload: dict[str, Any] = (jwt_get_claims(token=token,
387
+ errors=errors,
390
388
  logger=logger) or {}).get("payload")
391
389
  if errors:
392
390
  raise RuntimeError("; ".join(errors))
@@ -404,12 +402,11 @@ class JwtRegistry:
404
402
 
405
403
  # remove expired tokens from persistence
406
404
  if expired:
407
- db_delete(errors=errors,
408
- delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
405
+ db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
409
406
  where_data={JwtDbConfig.COL_KID: expired},
410
407
  engine=DbEngine(JwtDbConfig.ENGINE),
411
408
  connection=db_conn,
412
- committable=False,
409
+ errors=errors,
413
410
  logger=logger)
414
411
  if errors:
415
412
  raise RuntimeError("; ".join(errors))
@@ -419,12 +416,11 @@ class JwtRegistry:
419
416
 
420
417
  if 0 < JwtConfig.ACCOUNT_LIMIT.value <= len(recs) - len(expired):
421
418
  # delete the oldest token to make way for the new one
422
- db_delete(errors=errors,
423
- delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
419
+ db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
424
420
  where_data={JwtDbConfig.COL_KID: oldest_id},
425
421
  engine=DbEngine(JwtDbConfig.ENGINE),
426
422
  connection=db_conn,
427
- committable=False,
423
+ errors=errors,
428
424
  logger=logger)
429
425
  if errors:
430
426
  raise RuntimeError("; ".join(errors))
@@ -432,8 +428,7 @@ class JwtRegistry:
432
428
  logger.debug(msg="Oldest active token of account "
433
429
  f"'{account_id}' removed from storage")
434
430
  # persist token
435
- col_kid: int = db_insert(errors=errors,
436
- insert_stmt=f"INSERT INTO {JwtDbConfig.TABLE}",
431
+ col_kid: int = db_insert(insert_stmt=f"INSERT INTO {JwtDbConfig.TABLE}",
437
432
  insert_data={
438
433
  JwtDbConfig.COL_ACCOUNT: account_id,
439
434
  JwtDbConfig.COL_TOKEN: jwt_token,
@@ -443,14 +438,13 @@ class JwtRegistry:
443
438
  return_cols={JwtDbConfig.COL_KID: int},
444
439
  engine=DbEngine(JwtDbConfig.ENGINE),
445
440
  connection=db_conn,
446
- committable=False,
441
+ errors=errors,
447
442
  logger=logger)
448
443
  if errors:
449
444
  raise RuntimeError("; ".join(errors))
450
445
 
451
446
  # obtain and return the token's storage id
452
- reply: list[tuple[int]] = db_select(errors=errors,
453
- sel_stmt=f"SELECT {JwtDbConfig.COL_KID} "
447
+ reply: list[tuple[int]] = db_select(sel_stmt=f"SELECT {JwtDbConfig.COL_KID} "
454
448
  f"FROM {JwtDbConfig.TABLE}",
455
449
  where_data={JwtDbConfig.COL_KID: col_kid},
456
450
  min_count=1,
@@ -458,6 +452,7 @@ class JwtRegistry:
458
452
  engine=DbEngine(JwtDbConfig.ENGINE),
459
453
  connection=db_conn,
460
454
  committable=False,
455
+ errors=errors,
461
456
  logger=logger)
462
457
  if errors:
463
458
  raise RuntimeError("; ".join(errors))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypomes_jwt
3
- Version: 1.2.6
3
+ Version: 1.2.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
@@ -13,5 +13,5 @@ Requires-Python: >=3.12
13
13
  Requires-Dist: cryptography>=45.0.6
14
14
  Requires-Dist: flask>=3.1.1
15
15
  Requires-Dist: pyjwt>=2.10.1
16
- Requires-Dist: pypomes-core>=2.6.5
17
- Requires-Dist: pypomes-db>=2.4.8
16
+ Requires-Dist: pypomes-core>=2.7.0
17
+ Requires-Dist: pypomes-db>=2.5.7
@@ -0,0 +1,9 @@
1
+ pypomes_jwt/__init__.py,sha256=vXAeaEnuUqpvGtV465TsW2Lf3ihijrMP2Hm4My79y88,968
2
+ pypomes_jwt/jwt_config.py,sha256=3r9XPWXXAG_wKUs_FDZoTj9j6lmTdNymud_q4E4Opk0,3338
3
+ pypomes_jwt/jwt_pomes.py,sha256=u9TEe2oNpk6QlcpjnJ4-lH6WitkLjuDXLNTveeiFFqw,23784
4
+ pypomes_jwt/jwt_providers.py,sha256=wDIP6W-l_X1zrWeCNFGcRsb8Ui1Sja-3StcuRtLTjR4,5928
5
+ pypomes_jwt/jwt_registry.py,sha256=AyaoSK4KMhRiRACTImK5z0AzQBwhG5cBkazPjkrzdaI,22046
6
+ pypomes_jwt-1.2.7.dist-info/METADATA,sha256=ft9-OuYTf4hgDHVz2iMHyQC21emonjpZEdQ9oF5K9w8,660
7
+ pypomes_jwt-1.2.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ pypomes_jwt-1.2.7.dist-info/licenses/LICENSE,sha256=NdakochSXm_H_-DSL_x2JlRCkYikj3snYYvTwgR5d_c,1086
9
+ pypomes_jwt-1.2.7.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- pypomes_jwt/__init__.py,sha256=vXAeaEnuUqpvGtV465TsW2Lf3ihijrMP2Hm4My79y88,968
2
- pypomes_jwt/jwt_config.py,sha256=3r9XPWXXAG_wKUs_FDZoTj9j6lmTdNymud_q4E4Opk0,3338
3
- pypomes_jwt/jwt_pomes.py,sha256=em_apYg0ptfa5BvobnfXz7BPh_ghPhXGg7zHFK3A8y4,23901
4
- pypomes_jwt/jwt_providers.py,sha256=w66KBxGOHIht4eQLfAXAnLabJWjxfubPQk3rWfo_bmY,5787
5
- pypomes_jwt/jwt_registry.py,sha256=pNBpPiR2xINzNnWu_2dcPtRVfXqqPzMVYCXG1HtatUA,22268
6
- pypomes_jwt-1.2.6.dist-info/METADATA,sha256=W6rje1AuqC-Tkz8gQSCM0fhi5Vwsb6ToqpwiyYfWnXc,660
7
- pypomes_jwt-1.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- pypomes_jwt-1.2.6.dist-info/licenses/LICENSE,sha256=NdakochSXm_H_-DSL_x2JlRCkYikj3snYYvTwgR5d_c,1086
9
- pypomes_jwt-1.2.6.dist-info/RECORD,,