pypomes-jwt 1.0.8__py3-none-any.whl → 1.1.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.
Potentially problematic release.
This version of pypomes-jwt might be problematic. Click here for more details.
- pypomes_jwt/__init__.py +2 -12
- pypomes_jwt/jwt_constants.py +76 -39
- pypomes_jwt/jwt_pomes.py +22 -22
- pypomes_jwt/jwt_registry.py +34 -35
- {pypomes_jwt-1.0.8.dist-info → pypomes_jwt-1.1.0.dist-info}/METADATA +3 -3
- pypomes_jwt-1.1.0.dist-info/RECORD +8 -0
- pypomes_jwt-1.0.8.dist-info/RECORD +0 -8
- {pypomes_jwt-1.0.8.dist-info → pypomes_jwt-1.1.0.dist-info}/WHEEL +0 -0
- {pypomes_jwt-1.0.8.dist-info → pypomes_jwt-1.1.0.dist-info}/licenses/LICENSE +0 -0
pypomes_jwt/__init__.py
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
from .jwt_constants import (
|
|
2
|
-
|
|
3
|
-
JWT_DB_PORT, JWT_DB_USER, JWT_DB_PWD,
|
|
4
|
-
JWT_DB_TABLE, JWT_DB_COL_KID, JWT_DB_COL_ACCOUNT,
|
|
5
|
-
JWT_DB_COL_ALGORITHM, JWT_DB_COL_DECODER, JWT_DB_COL_TOKEN,
|
|
6
|
-
JWT_ACCOUNT_LIMIT, JWT_ENCODING_KEY, JWT_DECODING_KEY,
|
|
7
|
-
JWT_DEFAULT_ALGORITHM, JWT_ACCESS_MAX_AGE, JWT_REFRESH_MAX_AGE
|
|
2
|
+
JwtParam, JwtDbParam
|
|
8
3
|
)
|
|
9
4
|
from .jwt_pomes import (
|
|
10
5
|
jwt_needed, jwt_verify_request,
|
|
@@ -15,12 +10,7 @@ from .jwt_pomes import (
|
|
|
15
10
|
|
|
16
11
|
__all__ = [
|
|
17
12
|
# jwt_constants
|
|
18
|
-
"
|
|
19
|
-
"JWT_DB_PORT", "JWT_DB_USER", "JWT_DB_PWD",
|
|
20
|
-
"JWT_DB_TABLE", "JWT_DB_COL_KID", "JWT_DB_COL_ACCOUNT",
|
|
21
|
-
"JWT_DB_COL_ALGORITHM", "JWT_DB_COL_DECODER", "JWT_DB_COL_TOKEN",
|
|
22
|
-
"JWT_ACCOUNT_LIMIT", "JWT_ENCODING_KEY", "JWT_DECODING_KEY",
|
|
23
|
-
"JWT_DEFAULT_ALGORITHM", "JWT_ACCESS_MAX_AGE", "JWT_REFRESH_MAX_AGE",
|
|
13
|
+
"JwtParam", "JwtDbParam",
|
|
24
14
|
# jwt_pomes
|
|
25
15
|
"jwt_needed", "jwt_verify_request",
|
|
26
16
|
"jwt_assert_account", "jwt_set_account", "jwt_remove_account",
|
pypomes_jwt/jwt_constants.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from cryptography.hazmat.primitives import serialization
|
|
2
2
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
3
3
|
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey
|
|
4
|
+
from enum import StrEnum
|
|
4
5
|
from pypomes_core import (
|
|
5
6
|
APP_PREFIX,
|
|
6
7
|
env_get_str, env_get_bytes, env_get_int
|
|
@@ -8,51 +9,49 @@ from pypomes_core import (
|
|
|
8
9
|
from pypomes_db import DbEngine, db_setup
|
|
9
10
|
from secrets import token_bytes
|
|
10
11
|
from sys import stderr
|
|
11
|
-
from typing import Final
|
|
12
|
+
from typing import Any, Final
|
|
12
13
|
|
|
13
|
-
# database specs for token persistence
|
|
14
|
-
JWT_DB_HOST: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_HOST")
|
|
15
|
-
JWT_DB_NAME: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_NAME")
|
|
16
|
-
JWT_DB_PORT: Final[int] = env_get_int(key=f"{APP_PREFIX}_JWT_DB_PORT")
|
|
17
|
-
JWT_DB_USER: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_USER")
|
|
18
|
-
JWT_DB_PWD: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_PWD")
|
|
19
|
-
JWT_DB_CLIENT: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_CLIENT") # for Oracle, only
|
|
20
|
-
JWT_DB_DRIVER: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_DRIVER") # for SQLServer, only
|
|
21
|
-
JWT_DB_TABLE: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_TABLE")
|
|
22
|
-
JWT_DB_COL_ACCOUNT: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_ACCOUNT")
|
|
23
|
-
JWT_DB_COL_ALGORITHM: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_ALGORITHM")
|
|
24
|
-
JWT_DB_COL_DECODER: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_DECODER")
|
|
25
|
-
JWT_DB_COL_KID: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_KID")
|
|
26
|
-
JWT_DB_COL_TOKEN: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_TOKEN")
|
|
27
14
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
15
|
+
class JwtParam(StrEnum):
|
|
16
|
+
"""
|
|
17
|
+
Parameters for JWT provider access.
|
|
18
|
+
"""
|
|
19
|
+
ACCESS_MAX_AGE = "access-max-age"
|
|
20
|
+
ACCOUNT_LIMIT = "account-limit"
|
|
21
|
+
DECODING_KEY = "decoding-key"
|
|
22
|
+
DEFAULT_ALGORITHM = "default-algorithm"
|
|
23
|
+
ENCODING_KEY = "encoding-key"
|
|
24
|
+
REFRESH_MAX_AGE = "refresh-max-age"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class JwtDbParam(StrEnum):
|
|
28
|
+
"""
|
|
29
|
+
Parameters for JWT databse connection.
|
|
30
|
+
"""
|
|
31
|
+
CLIENT = "client"
|
|
32
|
+
DRIVER = "driver"
|
|
33
|
+
ENGINE = "engine"
|
|
34
|
+
NAME = "name"
|
|
35
|
+
HOST = "host"
|
|
36
|
+
PORT = "port"
|
|
37
|
+
USER = "user"
|
|
38
|
+
PWD = "pwd"
|
|
39
|
+
TABLE = "table"
|
|
40
|
+
COL_ACCOUNT = "col-account"
|
|
41
|
+
COL_ALGORITHM = "col-algorithm"
|
|
42
|
+
COL_DECODER = "col-decoder"
|
|
43
|
+
COL_KID = "col-kid"
|
|
44
|
+
COL_TOKEN = "col-token"
|
|
39
45
|
|
|
40
|
-
# one of HS256, HS512, RS256, RS512
|
|
41
|
-
JWT_DEFAULT_ALGORITHM: Final[str] = env_get_str(key=f"{APP_PREFIX}_JWT_DEFAULT_ALGORITHM",
|
|
42
|
-
def_value="RS256")
|
|
43
|
-
# recommended: between 5 min and 1 hour (set to 5 min)
|
|
44
|
-
JWT_ACCESS_MAX_AGE: Final[int] = env_get_int(key=f"{APP_PREFIX}_JWT_ACCESS_MAX_AGE",
|
|
45
|
-
def_value=300)
|
|
46
|
-
# recommended: at least 2 hours (set to 24 hours)
|
|
47
|
-
JWT_REFRESH_MAX_AGE: Final[int] = env_get_int(key=f"{APP_PREFIX}_JWT_REFRESH_MAX_AGE",
|
|
48
|
-
def_value=86400)
|
|
49
|
-
JWT_ACCOUNT_LIMIT: Final[int] = env_get_int(key=f"{APP_PREFIX}_JWT_ACCOUNT_LIMIT")
|
|
50
46
|
|
|
51
47
|
# recommended: allow the encode and decode keys to be generated anew when app starts
|
|
52
48
|
__encoding_key: bytes = env_get_bytes(key=f"{APP_PREFIX}_JWT_ENCODING_KEY",
|
|
53
49
|
encoding="base64url")
|
|
54
50
|
__decoding_key: bytes
|
|
55
|
-
|
|
51
|
+
# one of HS256, HS512, RS256, RS512
|
|
52
|
+
__default_algorithm: str = env_get_str(key=f"{APP_PREFIX}_JWT_DEFAULT_ALGORITHM",
|
|
53
|
+
def_value="RS256")
|
|
54
|
+
if __default_algorithm in ["HS256", "HS512"]:
|
|
56
55
|
if not __encoding_key:
|
|
57
56
|
__encoding_key = token_bytes(nbytes=32)
|
|
58
57
|
__decoding_key = __encoding_key
|
|
@@ -67,5 +66,43 @@ else:
|
|
|
67
66
|
__pub_key: RSAPublicKey = __priv_key.public_key()
|
|
68
67
|
__decoding_key = __pub_key.public_bytes(encoding=serialization.Encoding.PEM,
|
|
69
68
|
format=serialization.PublicFormat.SubjectPublicKeyInfo)
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
|
|
70
|
+
_JWT_CONFIG: Final[dict[JwtParam, Any]] = {
|
|
71
|
+
# recommended: between 5 min and 1 hour (set to 5 min)
|
|
72
|
+
JwtParam.ACCESS_MAX_AGE: env_get_int(key=f"{APP_PREFIX}_JWT_ACCESS_MAX_AGE",
|
|
73
|
+
def_value=300),
|
|
74
|
+
JwtParam.ACCOUNT_LIMIT: env_get_int(key=f"{APP_PREFIX}_JWT_ACCOUNT_LIMIT"),
|
|
75
|
+
JwtParam.DECODING_KEY: __decoding_key,
|
|
76
|
+
JwtParam.DEFAULT_ALGORITHM: __default_algorithm,
|
|
77
|
+
JwtParam.ENCODING_KEY: __encoding_key,
|
|
78
|
+
# recommended: at least 2 hours (set to 24 hours)
|
|
79
|
+
JwtParam.REFRESH_MAX_AGE: env_get_int(key=f"{APP_PREFIX}_JWT_REFRESH_MAX_AGE",
|
|
80
|
+
def_value=86400)
|
|
81
|
+
}
|
|
82
|
+
_JWT_DB: Final[JwtDbParam, Any] = {
|
|
83
|
+
JwtDbParam.ENGINE: DbEngine(env_get_str(key=f"{APP_PREFIX}_JWT_DB_ENGINE")),
|
|
84
|
+
JwtDbParam.CLIENT: env_get_str(key=f"{APP_PREFIX}_JWT_DB_CLIENT"), # for Oracle, only
|
|
85
|
+
JwtDbParam.DRIVER: env_get_str(key=f"{APP_PREFIX}_JWT_DB_DRIVER"), # for SQLServer, only
|
|
86
|
+
JwtDbParam.NAME: env_get_str(key=f"{APP_PREFIX}_JWT_DB_NAME"),
|
|
87
|
+
JwtDbParam.HOST: env_get_str(key=f"{APP_PREFIX}_JWT_DB_HOST"),
|
|
88
|
+
JwtDbParam.PORT: env_get_int(key=f"{APP_PREFIX}_JWT_DB_PORT"),
|
|
89
|
+
JwtDbParam.USER: env_get_str(key=f"{APP_PREFIX}_JWT_DB_USER"),
|
|
90
|
+
JwtDbParam.PWD: env_get_str(key=f"{APP_PREFIX}_JWT_DB_PWD"),
|
|
91
|
+
JwtDbParam.TABLE: env_get_str(key=f"{APP_PREFIX}_JWT_DB_TABLE"),
|
|
92
|
+
JwtDbParam.COL_ACCOUNT: env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_ACCOUNT"),
|
|
93
|
+
JwtDbParam.COL_ALGORITHM: env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_ALGORITHM"),
|
|
94
|
+
JwtDbParam.COL_DECODER: env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_DECODER"),
|
|
95
|
+
JwtDbParam.COL_KID: env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_KID"),
|
|
96
|
+
JwtDbParam.COL_TOKEN: env_get_str(key=f"{APP_PREFIX}_JWT_DB_COL_TOKEN")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# define and validate the database engine
|
|
100
|
+
if not db_setup(engine=_JWT_DB[JwtDbParam.ENGINE],
|
|
101
|
+
db_name=_JWT_DB[JwtDbParam.NAME],
|
|
102
|
+
db_user=_JWT_DB[JwtDbParam.USER],
|
|
103
|
+
db_pwd=_JWT_DB[JwtDbParam.PWD],
|
|
104
|
+
db_host=_JWT_DB[JwtDbParam.HOST],
|
|
105
|
+
db_port=_JWT_DB[JwtDbParam.PORT],
|
|
106
|
+
db_client=_JWT_DB[JwtDbParam.CLIENT],
|
|
107
|
+
db_driver=_JWT_DB[JwtDbParam.DRIVER]):
|
|
108
|
+
stderr.write("Invalid database parameters\n")
|
pypomes_jwt/jwt_pomes.py
CHANGED
|
@@ -9,15 +9,12 @@ from pypomes_db import (
|
|
|
9
9
|
)
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
-
from . import (
|
|
13
|
-
|
|
14
|
-
JWT_DEFAULT_ALGORITHM, JWT_DECODING_KEY,
|
|
15
|
-
JWT_DB_TABLE, JWT_DB_COL_KID,
|
|
16
|
-
JWT_DB_COL_ACCOUNT, JWT_DB_COL_ALGORITHM, JWT_DB_COL_DECODER
|
|
12
|
+
from .jwt_constants import (
|
|
13
|
+
JwtParam, JwtDbParam, _JWT_CONFIG, _JWT_DB
|
|
17
14
|
)
|
|
18
15
|
from .jwt_registry import JwtRegistry
|
|
19
16
|
|
|
20
|
-
# the JWT
|
|
17
|
+
# the JWT registry
|
|
21
18
|
__jwt_registry: JwtRegistry = JwtRegistry()
|
|
22
19
|
|
|
23
20
|
|
|
@@ -42,8 +39,8 @@ def jwt_verify_request(request: Request) -> Response:
|
|
|
42
39
|
"""
|
|
43
40
|
Verify whether the HTTP *request* has the proper authorization, as per the JWT standard.
|
|
44
41
|
|
|
45
|
-
:param request: the request to be verified
|
|
46
|
-
:return: *None* if the request is valid, otherwise a *Response*
|
|
42
|
+
:param request: the *request* to be verified
|
|
43
|
+
:return: *None* if the *request* is valid, otherwise a *Response* reporting the error
|
|
47
44
|
"""
|
|
48
45
|
# initialize the return variable
|
|
49
46
|
result: Response | None = None
|
|
@@ -80,8 +77,8 @@ def jwt_assert_account(account_id: str) -> bool:
|
|
|
80
77
|
|
|
81
78
|
def jwt_set_account(account_id: str,
|
|
82
79
|
claims: dict[str, Any],
|
|
83
|
-
access_max_age: int =
|
|
84
|
-
refresh_max_age: int =
|
|
80
|
+
access_max_age: int = _JWT_CONFIG[JwtParam.ACCESS_MAX_AGE],
|
|
81
|
+
refresh_max_age: int = _JWT_CONFIG[JwtParam.REFRESH_MAX_AGE],
|
|
85
82
|
grace_interval: int = None,
|
|
86
83
|
logger: Logger = None) -> None:
|
|
87
84
|
"""
|
|
@@ -182,12 +179,15 @@ def jwt_validate_token(errors: list[str] | None,
|
|
|
182
179
|
elif token_kid and len(token_kid) > 1 and \
|
|
183
180
|
token_kid[0:1] in ["A", "R"] and token_kid[1:].isdigit():
|
|
184
181
|
# token was likely issued locally
|
|
185
|
-
where_data: dict[str, Any] = {
|
|
182
|
+
where_data: dict[str, Any] = {
|
|
183
|
+
_JWT_DB[JwtDbParam.COL_KID]: int(token_kid[1:])
|
|
184
|
+
}
|
|
186
185
|
if account_id:
|
|
187
|
-
where_data[
|
|
186
|
+
where_data[_JWT_DB[JwtDbParam.COL_ACCOUNT]] = account_id
|
|
188
187
|
recs: list[tuple[str]] = db_select(errors=op_errors,
|
|
189
|
-
sel_stmt=f"SELECT {
|
|
190
|
-
f"
|
|
188
|
+
sel_stmt=f"SELECT {_JWT_DB[JwtDbParam.COL_ALGORITHM]}, "
|
|
189
|
+
f"{_JWT_DB[JwtDbParam.COL_DECODER]} "
|
|
190
|
+
f"FROM {_JWT_DB[JwtDbParam.TABLE]}",
|
|
191
191
|
where_data=where_data,
|
|
192
192
|
logger=logger)
|
|
193
193
|
if recs:
|
|
@@ -201,8 +201,8 @@ def jwt_validate_token(errors: list[str] | None,
|
|
|
201
201
|
logger.error(msg="Token not in the database")
|
|
202
202
|
op_errors.append("Invalid token")
|
|
203
203
|
else:
|
|
204
|
-
token_alg =
|
|
205
|
-
token_decoder =
|
|
204
|
+
token_alg = _JWT_CONFIG[JwtParam.DEFAULT_ALGORITHM]
|
|
205
|
+
token_decoder = _JWT_CONFIG[JwtParam.DECODING_KEY]
|
|
206
206
|
|
|
207
207
|
# validate the token
|
|
208
208
|
if not op_errors:
|
|
@@ -282,10 +282,10 @@ def jwt_revoke_token(errors: list[str] | None,
|
|
|
282
282
|
op_errors.append("Invalid token")
|
|
283
283
|
else:
|
|
284
284
|
db_delete(errors=op_errors,
|
|
285
|
-
delete_stmt=f"DELETE FROM {
|
|
285
|
+
delete_stmt=f"DELETE FROM {_JWT_DB[JwtDbParam.TABLE]}",
|
|
286
286
|
where_data={
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
_JWT_DB[JwtDbParam.COL_KID]: int(token_kid[1:]),
|
|
288
|
+
_JWT_DB[JwtDbParam.COL_ACCOUNT]: account_id
|
|
289
289
|
},
|
|
290
290
|
logger=logger)
|
|
291
291
|
if op_errors:
|
|
@@ -456,10 +456,10 @@ def jwt_refresh_tokens(errors: list[str] | None,
|
|
|
456
456
|
if db_conn:
|
|
457
457
|
# delete current refresh token
|
|
458
458
|
db_delete(errors=op_errors,
|
|
459
|
-
delete_stmt=f"DELETE FROM {
|
|
459
|
+
delete_stmt=f"DELETE FROM {_JWT_DB[JwtDbParam.TABLE]}",
|
|
460
460
|
where_data={
|
|
461
|
-
|
|
462
|
-
|
|
461
|
+
_JWT_DB[JwtDbParam.COL_KID]: int(token_kid[1:]),
|
|
462
|
+
_JWT_DB[JwtDbParam.COL_ACCOUNT]: account_id
|
|
463
463
|
},
|
|
464
464
|
connection=db_conn,
|
|
465
465
|
committable=False,
|
pypomes_jwt/jwt_registry.py
CHANGED
|
@@ -12,11 +12,8 @@ from pypomes_db import (
|
|
|
12
12
|
from threading import Lock
|
|
13
13
|
from typing import Any
|
|
14
14
|
|
|
15
|
-
from . import (
|
|
16
|
-
|
|
17
|
-
JWT_ENCODING_KEY, JWT_DECODING_KEY,
|
|
18
|
-
JWT_DB_TABLE, JWT_DB_COL_KID, JWT_DB_COL_ACCOUNT,
|
|
19
|
-
JWT_DB_COL_ALGORITHM, JWT_DB_COL_DECODER, JWT_DB_COL_TOKEN
|
|
15
|
+
from .jwt_constants import (
|
|
16
|
+
JwtParam, JwtDbParam, _JWT_CONFIG, _JWT_DB
|
|
20
17
|
)
|
|
21
18
|
|
|
22
19
|
|
|
@@ -144,8 +141,8 @@ class JwtRegistry:
|
|
|
144
141
|
|
|
145
142
|
# remove from database
|
|
146
143
|
db_delete(errors=None,
|
|
147
|
-
delete_stmt=f"DELETE FROM {
|
|
148
|
-
where_data={
|
|
144
|
+
delete_stmt=f"DELETE FROM {_JWT_DB[JwtDbParam.TABLE]}",
|
|
145
|
+
where_data={_JWT_DB[JwtDbParam.COL_ACCOUNT]: account_id},
|
|
149
146
|
logger=logger)
|
|
150
147
|
if logger:
|
|
151
148
|
if account_data:
|
|
@@ -219,8 +216,8 @@ class JwtRegistry:
|
|
|
219
216
|
tz=timezone.utc).isoformat()
|
|
220
217
|
# may raise an exception
|
|
221
218
|
return jwt.encode(payload=current_claims,
|
|
222
|
-
key=
|
|
223
|
-
algorithm=
|
|
219
|
+
key=_JWT_CONFIG[JwtParam.ENCODING_KEY],
|
|
220
|
+
algorithm=_JWT_CONFIG[JwtParam.DEFAULT_ALGORITHM],
|
|
224
221
|
headers={"kid": nature})
|
|
225
222
|
|
|
226
223
|
def issue_tokens(self,
|
|
@@ -280,8 +277,8 @@ class JwtRegistry:
|
|
|
280
277
|
tz=timezone.utc).isoformat()
|
|
281
278
|
# may raise an exception
|
|
282
279
|
refresh_token: str = jwt.encode(payload=current_claims,
|
|
283
|
-
key=
|
|
284
|
-
algorithm=
|
|
280
|
+
key=_JWT_CONFIG[JwtParam.ENCODING_KEY],
|
|
281
|
+
algorithm=_JWT_CONFIG[JwtParam.DEFAULT_ALGORITHM],
|
|
285
282
|
headers={"kid": "R0"})
|
|
286
283
|
|
|
287
284
|
# make sure to have a database connection
|
|
@@ -296,14 +293,14 @@ class JwtRegistry:
|
|
|
296
293
|
logger=logger)
|
|
297
294
|
# issue the definitive refresh token
|
|
298
295
|
refresh_token = jwt.encode(payload=current_claims,
|
|
299
|
-
key=
|
|
300
|
-
algorithm=
|
|
296
|
+
key=_JWT_CONFIG[JwtParam.ENCODING_KEY],
|
|
297
|
+
algorithm=_JWT_CONFIG[JwtParam.DEFAULT_ALGORITHM],
|
|
301
298
|
headers={"kid": f"R{token_id}"})
|
|
302
299
|
# persist it
|
|
303
300
|
db_update(errors=errors,
|
|
304
|
-
update_stmt=f"UPDATE {
|
|
305
|
-
update_data={
|
|
306
|
-
where_data={
|
|
301
|
+
update_stmt=f"UPDATE {_JWT_DB[JwtDbParam.TABLE]}",
|
|
302
|
+
update_data={_JWT_DB[JwtDbParam.COL_TOKEN]: refresh_token},
|
|
303
|
+
where_data={_JWT_DB[JwtDbParam.COL_KID]: token_id},
|
|
307
304
|
connection=curr_conn,
|
|
308
305
|
committable=False,
|
|
309
306
|
logger=logger)
|
|
@@ -325,8 +322,8 @@ class JwtRegistry:
|
|
|
325
322
|
current_claims["exp"] = just_now + account_data.get("access-max-age")
|
|
326
323
|
# may raise an exception
|
|
327
324
|
access_token: str = jwt.encode(payload=current_claims,
|
|
328
|
-
key=
|
|
329
|
-
algorithm=
|
|
325
|
+
key=_JWT_CONFIG[JwtParam.ENCODING_KEY],
|
|
326
|
+
algorithm=_JWT_CONFIG[JwtParam.DEFAULT_ALGORITHM],
|
|
330
327
|
headers={"kid": f"A{token_id}"})
|
|
331
328
|
# return the token data
|
|
332
329
|
return {
|
|
@@ -384,9 +381,9 @@ def _jwt_persist_token(account_id: str,
|
|
|
384
381
|
# noinspection PyTypeChecker
|
|
385
382
|
recs: list[tuple[int, str, str, str]] = \
|
|
386
383
|
db_select(errors=errors,
|
|
387
|
-
sel_stmt=f"SELECT {
|
|
388
|
-
f"FROM {
|
|
389
|
-
where_data={
|
|
384
|
+
sel_stmt=f"SELECT {_JWT_DB[JwtDbParam.COL_KID]}, {_JWT_DB[JwtDbParam.COL_TOKEN]} "
|
|
385
|
+
f"FROM {_JWT_DB[JwtDbParam.TABLE]}",
|
|
386
|
+
where_data={_JWT_DB[JwtDbParam.COL_ACCOUNT]: account_id},
|
|
390
387
|
connection=db_conn,
|
|
391
388
|
committable=False,
|
|
392
389
|
logger=logger)
|
|
@@ -427,8 +424,8 @@ def _jwt_persist_token(account_id: str,
|
|
|
427
424
|
# remove expired tokens from persistence
|
|
428
425
|
if expired:
|
|
429
426
|
db_delete(errors=errors,
|
|
430
|
-
delete_stmt=f"DELETE FROM {
|
|
431
|
-
where_data={
|
|
427
|
+
delete_stmt=f"DELETE FROM {_JWT_DB[JwtDbParam.TABLE]}",
|
|
428
|
+
where_data={_JWT_DB[JwtDbParam.COL_KID]: expired},
|
|
432
429
|
connection=db_conn,
|
|
433
430
|
committable=False,
|
|
434
431
|
logger=logger)
|
|
@@ -438,11 +435,11 @@ def _jwt_persist_token(account_id: str,
|
|
|
438
435
|
logger.debug(msg=f"{len(expired)} tokens of account "
|
|
439
436
|
f"'{account_id}' removed from storage")
|
|
440
437
|
|
|
441
|
-
if 0 <
|
|
438
|
+
if 0 < _JWT_CONFIG[JwtParam.ACCOUNT_LIMIT] <= len(recs) - len(expired):
|
|
442
439
|
# delete the oldest token to make way for the new one
|
|
443
440
|
db_delete(errors=errors,
|
|
444
|
-
delete_stmt=f"DELETE FROM {
|
|
445
|
-
where_data={
|
|
441
|
+
delete_stmt=f"DELETE FROM {_JWT_DB[JwtDbParam.TABLE]}",
|
|
442
|
+
where_data={_JWT_DB[JwtDbParam.COL_KID]: oldest_id},
|
|
446
443
|
connection=db_conn,
|
|
447
444
|
committable=False,
|
|
448
445
|
logger=logger)
|
|
@@ -453,11 +450,13 @@ def _jwt_persist_token(account_id: str,
|
|
|
453
450
|
f"'{account_id}' removed from storage")
|
|
454
451
|
# persist token
|
|
455
452
|
db_insert(errors=errors,
|
|
456
|
-
insert_stmt=f"INSERT INTO {
|
|
457
|
-
insert_data={
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
453
|
+
insert_stmt=f"INSERT INTO {_JWT_DB[JwtDbParam.TABLE]}",
|
|
454
|
+
insert_data={
|
|
455
|
+
_JWT_DB[JwtDbParam.COL_ACCOUNT]: account_id,
|
|
456
|
+
_JWT_DB[JwtDbParam.COL_TOKEN]: jwt_token,
|
|
457
|
+
_JWT_DB[JwtDbParam.COL_ALGORITHM]: _JWT_CONFIG[JwtParam.DEFAULT_ALGORITHM],
|
|
458
|
+
_JWT_DB[JwtDbParam.COL_DECODER]: urlsafe_b64encode(_JWT_CONFIG[JwtParam.DECODING_KEY]).decode()
|
|
459
|
+
},
|
|
461
460
|
connection=db_conn,
|
|
462
461
|
committable=False,
|
|
463
462
|
logger=logger)
|
|
@@ -468,13 +467,13 @@ def _jwt_persist_token(account_id: str,
|
|
|
468
467
|
# HAZARD: JWT_DB_COL_TOKEN's column type might prevent it for being used in a WHERE clause
|
|
469
468
|
where_clause: str | None = None
|
|
470
469
|
if existing_ids:
|
|
471
|
-
where_clause = f"{
|
|
470
|
+
where_clause = f"{_JWT_DB[JwtDbParam.COL_KID]} NOT IN {existing_ids}"
|
|
472
471
|
where_clause = where_clause.replace("[", "(", 1).replace("]", ")", 1)
|
|
473
472
|
reply: list[tuple[int]] = db_select(errors=errors,
|
|
474
|
-
sel_stmt=f"SELECT {
|
|
475
|
-
f"FROM {
|
|
473
|
+
sel_stmt=f"SELECT {_JWT_DB[JwtDbParam.COL_KID]} "
|
|
474
|
+
f"FROM {_JWT_DB[JwtDbParam.TABLE]}",
|
|
476
475
|
where_clause=where_clause,
|
|
477
|
-
where_data={
|
|
476
|
+
where_data={_JWT_DB[JwtDbParam.COL_ACCOUNT]: account_id},
|
|
478
477
|
require_count=1,
|
|
479
478
|
connection=db_conn,
|
|
480
479
|
committable=False,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pypomes_jwt
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
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
|
|
@@ -12,5 +12,5 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Requires-Dist: cryptography>=44.0.2
|
|
14
14
|
Requires-Dist: pyjwt>=2.10.1
|
|
15
|
-
Requires-Dist: pypomes-core>=1.9.
|
|
16
|
-
Requires-Dist: pypomes-db>=2.0.
|
|
15
|
+
Requires-Dist: pypomes-core>=1.9.6
|
|
16
|
+
Requires-Dist: pypomes-db>=2.0.9
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
pypomes_jwt/__init__.py,sha256=h6T8GEd2HX8mguRvSLiemE2FKC5rJnVnHipounnUT7U,792
|
|
2
|
+
pypomes_jwt/jwt_constants.py,sha256=5iPiDlO_D5DPUO90p8byiJZuvNlOeJYnDNety44dOVQ,4936
|
|
3
|
+
pypomes_jwt/jwt_pomes.py,sha256=SzieR_GPMaqWhoGT0T_zg17EGLdzPkVj9LoHEiqQt7Y,23394
|
|
4
|
+
pypomes_jwt/jwt_registry.py,sha256=CHIEjje1VROaxHmsSQxs1xCXF7E00Src55GHdzFvSzI,23352
|
|
5
|
+
pypomes_jwt-1.1.0.dist-info/METADATA,sha256=q3z3nivSzhSqRZ5wZDxVu6wDEKCh72pRiR8nRK7gRIg,632
|
|
6
|
+
pypomes_jwt-1.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
+
pypomes_jwt-1.1.0.dist-info/licenses/LICENSE,sha256=NdakochSXm_H_-DSL_x2JlRCkYikj3snYYvTwgR5d_c,1086
|
|
8
|
+
pypomes_jwt-1.1.0.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
pypomes_jwt/__init__.py,sha256=fLr_M8yXlcmSTNPMdJOJQlMmtaiK5YKh0vKjOp3z2E4,1446
|
|
2
|
-
pypomes_jwt/jwt_constants.py,sha256=IQV39AiZKGuU8XxZBgJ-KJZQZ_mmnxyOnRZeuxlqDRk,4045
|
|
3
|
-
pypomes_jwt/jwt_pomes.py,sha256=Oh4j6sj8DnQaVKzfFkPcCIZU590jXgNoMpWzyKYIdUQ,23224
|
|
4
|
-
pypomes_jwt/jwt_registry.py,sha256=S_-M6rcXwKy73H6uE4EwFx4F1gVfVg_DHCVYsqAbiWU,23005
|
|
5
|
-
pypomes_jwt-1.0.8.dist-info/METADATA,sha256=G3tsXNOnY332OdUz70cngOC9PP4zAwe-X3avwVJPhHM,632
|
|
6
|
-
pypomes_jwt-1.0.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
-
pypomes_jwt-1.0.8.dist-info/licenses/LICENSE,sha256=NdakochSXm_H_-DSL_x2JlRCkYikj3snYYvTwgR5d_c,1086
|
|
8
|
-
pypomes_jwt-1.0.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|