pypomes-jwt 0.9.9__tar.gz → 1.0.1__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.
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/PKG-INFO +1 -1
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/pyproject.toml +1 -1
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/src/pypomes_jwt/jwt_pomes.py +41 -32
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/.gitignore +0 -0
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/LICENSE +0 -0
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/README.md +0 -0
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/src/pypomes_jwt/__init__.py +0 -0
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/src/pypomes_jwt/jwt_constants.py +0 -0
- {pypomes_jwt-0.9.9 → pypomes_jwt-1.0.1}/src/pypomes_jwt/jwt_registry.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pypomes_jwt
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.1
|
|
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
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import jwt
|
|
2
|
+
import sys
|
|
2
3
|
from base64 import urlsafe_b64decode
|
|
3
4
|
from flask import Request, Response, request
|
|
4
5
|
from logging import Logger
|
|
6
|
+
from pypomes_core import exc_format
|
|
5
7
|
from pypomes_db import db_select, db_delete
|
|
6
8
|
from typing import Any
|
|
7
9
|
|
|
@@ -34,45 +36,33 @@ def jwt_needed(func: callable) -> callable:
|
|
|
34
36
|
return wrapper
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
def jwt_verify_request(request: Request
|
|
38
|
-
logger: Logger = None) -> Response:
|
|
39
|
+
def jwt_verify_request(request: Request) -> Response:
|
|
39
40
|
"""
|
|
40
|
-
Verify
|
|
41
|
+
Verify whether the HTTP *request* has the proper authorization, as per the JWT standard.
|
|
41
42
|
|
|
42
43
|
:param request: the request to be verified
|
|
43
|
-
:param logger: optional logger
|
|
44
44
|
:return: *None* if the request is valid, otherwise a *Response* object reporting the error
|
|
45
45
|
"""
|
|
46
46
|
# initialize the return variable
|
|
47
47
|
result: Response | None = None
|
|
48
48
|
|
|
49
|
-
if logger:
|
|
50
|
-
logger.debug(msg="Validate a JWT token")
|
|
51
|
-
err_msg: str | None = None
|
|
52
|
-
|
|
53
49
|
# retrieve the authorization from the request header
|
|
54
50
|
auth_header: str = request.headers.get("Authorization")
|
|
55
51
|
|
|
56
52
|
# was a 'Bearer' authorization obtained ?
|
|
53
|
+
bad_token: bool = False
|
|
57
54
|
if auth_header and auth_header.startswith("Bearer "):
|
|
58
55
|
# yes, extract and validate the JWT access token
|
|
59
56
|
token: str = auth_header.split(" ")[1]
|
|
60
|
-
if logger:
|
|
61
|
-
logger.debug(msg="Bearer token was retrieved")
|
|
62
57
|
errors: list[str] = []
|
|
63
58
|
jwt_validate_token(errors=errors,
|
|
64
59
|
nature="A",
|
|
65
60
|
token=token)
|
|
66
61
|
if errors:
|
|
67
|
-
|
|
68
|
-
else:
|
|
69
|
-
# no 'Bearer' found, report the error
|
|
70
|
-
err_msg = "Request header has no 'Bearer' data"
|
|
62
|
+
bad_token = True
|
|
71
63
|
|
|
72
|
-
#
|
|
73
|
-
if
|
|
74
|
-
if logger:
|
|
75
|
-
logger.error(msg=err_msg)
|
|
64
|
+
# deny the authorization
|
|
65
|
+
if bad_token:
|
|
76
66
|
result = Response(response="Authorization failed",
|
|
77
67
|
status=401)
|
|
78
68
|
return result
|
|
@@ -152,6 +142,8 @@ def jwt_validate_token(errors: list[str] | None,
|
|
|
152
142
|
If the *kid* claim contains such an id, then the cryptographic key needed for validation
|
|
153
143
|
will be obtained from the token database. Otherwise, the current decoding key is used.
|
|
154
144
|
|
|
145
|
+
On success, return the token's claims (header and payload), as documented in *jwt_get_claims()*
|
|
146
|
+
|
|
155
147
|
:param errors: incidental error messages
|
|
156
148
|
:param token: the token to be validated
|
|
157
149
|
:param nature: prefix identifying the nature of locally issued tokens
|
|
@@ -171,7 +163,11 @@ def jwt_validate_token(errors: list[str] | None,
|
|
|
171
163
|
try:
|
|
172
164
|
token_header: dict[str, Any] = jwt.get_unverified_header(jwt=token)
|
|
173
165
|
except Exception as e:
|
|
174
|
-
|
|
166
|
+
exc_err: str = exc_format(exc=e,
|
|
167
|
+
exc_info=sys.exc_info())
|
|
168
|
+
if logger:
|
|
169
|
+
logger.error(msg=f"Error retrieving the token's header: {exc_err}")
|
|
170
|
+
op_errors.append(exc_err)
|
|
175
171
|
|
|
176
172
|
if not op_errors:
|
|
177
173
|
token_kid: str = token_header.get("kid")
|
|
@@ -195,7 +191,12 @@ def jwt_validate_token(errors: list[str] | None,
|
|
|
195
191
|
if recs:
|
|
196
192
|
token_alg = recs[0][0]
|
|
197
193
|
token_decoder = urlsafe_b64decode(recs[0][1])
|
|
194
|
+
elif op_errors:
|
|
195
|
+
if logger:
|
|
196
|
+
logger.error(msg=f"Error retrieving the token's decoder: {'; '.join(op_errors)}")
|
|
198
197
|
else:
|
|
198
|
+
if logger:
|
|
199
|
+
logger.error(msg="Token not in the database")
|
|
199
200
|
op_errors.append("Invalid token")
|
|
200
201
|
else:
|
|
201
202
|
token_alg = JWT_DEFAULT_ALGORITHM
|
|
@@ -230,12 +231,13 @@ def jwt_validate_token(errors: list[str] | None,
|
|
|
230
231
|
"payload": payload
|
|
231
232
|
}
|
|
232
233
|
except Exception as e:
|
|
233
|
-
|
|
234
|
+
exc_err: str = exc_format(exc=e,
|
|
235
|
+
exc_info=sys.exc_info())
|
|
236
|
+
if logger:
|
|
237
|
+
logger.error(msg=f"Error decoding the token: {exc_err}")
|
|
238
|
+
op_errors.append(exc_err)
|
|
234
239
|
|
|
235
240
|
if op_errors:
|
|
236
|
-
err_msg: str = "; ".join(op_errors)
|
|
237
|
-
if logger:
|
|
238
|
-
logger.error(msg=err_msg)
|
|
239
241
|
if isinstance(errors, list):
|
|
240
242
|
errors.extend(op_errors)
|
|
241
243
|
elif logger:
|
|
@@ -335,13 +337,14 @@ def jwt_issue_token(errors: list[str] | None,
|
|
|
335
337
|
logger.debug(msg=f"Token is '{result}'")
|
|
336
338
|
except Exception as e:
|
|
337
339
|
# token issuing failed
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if op_errors:
|
|
340
|
+
exc_err: str = exc_format(exc=e,
|
|
341
|
+
exc_info=sys.exc_info())
|
|
341
342
|
if logger:
|
|
342
|
-
logger.error("
|
|
343
|
-
|
|
344
|
-
|
|
343
|
+
logger.error(msg=f"Error issuing the token: {exc_err}")
|
|
344
|
+
op_errors.append(exc_err)
|
|
345
|
+
|
|
346
|
+
if op_errors and isinstance(errors, list):
|
|
347
|
+
errors.extend(op_errors)
|
|
345
348
|
|
|
346
349
|
return result
|
|
347
350
|
|
|
@@ -385,7 +388,11 @@ def jwt_issue_tokens(errors: list[str] | None,
|
|
|
385
388
|
logger.debug(msg=f"Token data is '{result}'")
|
|
386
389
|
except Exception as e:
|
|
387
390
|
# token issuing failed
|
|
388
|
-
|
|
391
|
+
exc_err: str = exc_format(exc=e,
|
|
392
|
+
exc_info=sys.exc_info())
|
|
393
|
+
if logger:
|
|
394
|
+
logger.error(msg=f"Error issuing the token pair: {exc_err}")
|
|
395
|
+
op_errors.append(exc_err)
|
|
389
396
|
|
|
390
397
|
if op_errors:
|
|
391
398
|
if logger:
|
|
@@ -512,9 +519,11 @@ def jwt_get_claims(errors: list[str] | None,
|
|
|
512
519
|
"payload": payload
|
|
513
520
|
}
|
|
514
521
|
except Exception as e:
|
|
522
|
+
exc_err: str = exc_format(exc=e,
|
|
523
|
+
exc_info=sys.exc_info())
|
|
515
524
|
if logger:
|
|
516
|
-
logger.error(msg=
|
|
525
|
+
logger.error(msg=f"Error retrieving the token's claimsn: {exc_err}")
|
|
517
526
|
if isinstance(errors, list):
|
|
518
|
-
errors.append(
|
|
527
|
+
errors.append(exc_err)
|
|
519
528
|
|
|
520
529
|
return result
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|