pypomes-iam 0.5.5__py3-none-any.whl → 0.5.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-iam might be problematic. Click here for more details.
- pypomes_iam/__init__.py +12 -9
- pypomes_iam/{iam_pomes.py → iam_actions.py} +22 -97
- pypomes_iam/iam_common.py +54 -9
- pypomes_iam/iam_services.py +109 -24
- pypomes_iam/jusbr_pomes.py +5 -5
- pypomes_iam/keycloak_pomes.py +5 -5
- pypomes_iam/provider_pomes.py +2 -2
- {pypomes_iam-0.5.5.dist-info → pypomes_iam-0.5.7.dist-info}/METADATA +1 -1
- pypomes_iam-0.5.7.dist-info/RECORD +12 -0
- pypomes_iam-0.5.5.dist-info/RECORD +0 -12
- {pypomes_iam-0.5.5.dist-info → pypomes_iam-0.5.7.dist-info}/WHEEL +0 -0
- {pypomes_iam-0.5.5.dist-info → pypomes_iam-0.5.7.dist-info}/licenses/LICENSE +0 -0
pypomes_iam/__init__.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
from .
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
from .iam_actions import (
|
|
2
|
+
action_callback, action_exchange,
|
|
3
|
+
action_login, action_logout, action_token
|
|
4
|
+
)
|
|
5
|
+
from .iam_common import (
|
|
6
|
+
IamServer
|
|
5
7
|
)
|
|
6
8
|
from .iam_services import (
|
|
7
|
-
logger_register
|
|
9
|
+
jwt_required, logger_register
|
|
8
10
|
)
|
|
9
11
|
from .jusbr_pomes import (
|
|
10
12
|
jusbr_setup, jusbr_get_token
|
|
@@ -20,12 +22,13 @@ from .token_pomes import (
|
|
|
20
22
|
)
|
|
21
23
|
|
|
22
24
|
__all__ = [
|
|
23
|
-
#
|
|
25
|
+
# iam_actions
|
|
26
|
+
"action_callback", "action_exchange",
|
|
27
|
+
"action_login", "action_logout", "action_token",
|
|
28
|
+
# iam_commons
|
|
24
29
|
"IamServer",
|
|
25
|
-
"login_callback", "token_exchange",
|
|
26
|
-
"user_login", "user_logout", "user_token",
|
|
27
30
|
# iam_services
|
|
28
|
-
"logger_register",
|
|
31
|
+
"jwt_required", "logger_register",
|
|
29
32
|
# jusbr_pomes
|
|
30
33
|
"jusbr_setup", "jusbr_get_token",
|
|
31
34
|
# keycloak_pomes
|
|
@@ -4,7 +4,6 @@ import secrets
|
|
|
4
4
|
import string
|
|
5
5
|
import sys
|
|
6
6
|
from datetime import datetime
|
|
7
|
-
from flask import Request, Response, request
|
|
8
7
|
from logging import Logger
|
|
9
8
|
from pypomes_core import TZ_LOCAL, exc_format
|
|
10
9
|
from typing import Any
|
|
@@ -12,32 +11,15 @@ from typing import Any
|
|
|
12
11
|
from .iam_common import (
|
|
13
12
|
IamServer, _iam_lock,
|
|
14
13
|
_get_iam_users, _get_iam_registry, # _get_public_key,
|
|
15
|
-
_get_login_timeout, _get_user_data
|
|
14
|
+
_get_login_timeout, _get_user_data
|
|
16
15
|
)
|
|
17
|
-
from .token_pomes import
|
|
16
|
+
from .token_pomes import token_validate
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
:param func: the function being decorated
|
|
25
|
-
"""
|
|
26
|
-
# ruff: noqa: ANN003 - Missing type annotation for *{name}
|
|
27
|
-
def wrapper(*args, **kwargs) -> Response:
|
|
28
|
-
response: Response = __request_validate(request=request)
|
|
29
|
-
return response if response else func(*args, **kwargs)
|
|
30
|
-
|
|
31
|
-
# prevent a rogue error ("View function mapping is overwriting an existing endpoint function")
|
|
32
|
-
wrapper.__name__ = func.__name__
|
|
33
|
-
|
|
34
|
-
return wrapper
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def user_login(iam_server: IamServer,
|
|
38
|
-
args: dict[str, Any],
|
|
39
|
-
errors: list[str] = None,
|
|
40
|
-
logger: Logger = None) -> str:
|
|
19
|
+
def action_login(iam_server: IamServer,
|
|
20
|
+
args: dict[str, Any],
|
|
21
|
+
errors: list[str] = None,
|
|
22
|
+
logger: Logger = None) -> str:
|
|
41
23
|
"""
|
|
42
24
|
Build the URL for redirecting the request to *iam_server*'s authentication page.
|
|
43
25
|
|
|
@@ -95,10 +77,10 @@ def user_login(iam_server: IamServer,
|
|
|
95
77
|
return result
|
|
96
78
|
|
|
97
79
|
|
|
98
|
-
def
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
80
|
+
def action_logout(iam_server: IamServer,
|
|
81
|
+
args: dict[str, Any],
|
|
82
|
+
errors: list[str] = None,
|
|
83
|
+
logger: Logger = None) -> None:
|
|
102
84
|
"""
|
|
103
85
|
Logout the user, by removing all data associating it from *iam_server*'s registry.
|
|
104
86
|
|
|
@@ -126,10 +108,10 @@ def user_logout(iam_server: IamServer,
|
|
|
126
108
|
logger.debug(msg=f"User '{user_id}' removed from {iam_server}'s registry")
|
|
127
109
|
|
|
128
110
|
|
|
129
|
-
def
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
111
|
+
def action_token(iam_server: IamServer,
|
|
112
|
+
args: dict[str, Any],
|
|
113
|
+
errors: list[str] = None,
|
|
114
|
+
logger: Logger = None) -> str:
|
|
133
115
|
"""
|
|
134
116
|
Retrieve the authentication token for the user, from *iam_server*.
|
|
135
117
|
|
|
@@ -212,10 +194,10 @@ def user_token(iam_server: IamServer,
|
|
|
212
194
|
return result
|
|
213
195
|
|
|
214
196
|
|
|
215
|
-
def
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
197
|
+
def action_callback(iam_server: IamServer,
|
|
198
|
+
args: dict[str, Any],
|
|
199
|
+
errors: list[str] = None,
|
|
200
|
+
logger: Logger = None) -> tuple[str, str] | None:
|
|
219
201
|
"""
|
|
220
202
|
Entry point for the callback from *iam_server* via the front-end application, on authentication operations.
|
|
221
203
|
|
|
@@ -282,10 +264,10 @@ def login_callback(iam_server: IamServer,
|
|
|
282
264
|
return result
|
|
283
265
|
|
|
284
266
|
|
|
285
|
-
def
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
267
|
+
def action_exchange(iam_server: IamServer,
|
|
268
|
+
args: dict[str, Any],
|
|
269
|
+
errors: list[str] = None,
|
|
270
|
+
logger: Logger = None) -> dict[str, Any]:
|
|
289
271
|
"""
|
|
290
272
|
Request *iam_server* to issue a token in exchange for the token obtained from another *IAM* server.
|
|
291
273
|
|
|
@@ -357,63 +339,6 @@ def token_exchange(iam_server: IamServer,
|
|
|
357
339
|
return result
|
|
358
340
|
|
|
359
341
|
|
|
360
|
-
def __request_validate(request: Request) -> Response:
|
|
361
|
-
"""
|
|
362
|
-
Verify whether the HTTP *request* has the proper authorization, as per the JWT standard.
|
|
363
|
-
|
|
364
|
-
This implementation assumes that HTTP requests are handled with the *Flask* framework.
|
|
365
|
-
|
|
366
|
-
:param request: the *request* to be verified
|
|
367
|
-
:return: *None* if the *request* is valid, otherwise a *Response* reporting the error
|
|
368
|
-
"""
|
|
369
|
-
# initialize the return variable
|
|
370
|
-
result: Response | None = None
|
|
371
|
-
|
|
372
|
-
# retrieve the authorization from the request header
|
|
373
|
-
auth_header: str = request.headers.get("Authorization")
|
|
374
|
-
|
|
375
|
-
# validate the authorization token
|
|
376
|
-
bad_token: bool = True
|
|
377
|
-
if auth_header and auth_header.startswith("Bearer "):
|
|
378
|
-
# extract and validate the JWT access token
|
|
379
|
-
token: str = auth_header.split(" ")[1]
|
|
380
|
-
claims: dict[str, Any] = token_get_claims(token=token)
|
|
381
|
-
if claims:
|
|
382
|
-
issuer: str = claims["payload"].get("iss")
|
|
383
|
-
recipient_attr: str | None = None
|
|
384
|
-
recipient_id: str = request.values.get("user-id") or request.values.get("login")
|
|
385
|
-
with _iam_lock:
|
|
386
|
-
iam_server: IamServer = _iam_server_from_issuer(issuer=issuer,
|
|
387
|
-
errors=None,
|
|
388
|
-
logger=None)
|
|
389
|
-
# public_key: str = _get_public_key(iam_server=iam_server,
|
|
390
|
-
# errors=errors,
|
|
391
|
-
# logger=logger)
|
|
392
|
-
public_key = None
|
|
393
|
-
|
|
394
|
-
# validate the token's recipient only if a user identification is provided
|
|
395
|
-
if recipient_id:
|
|
396
|
-
registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
|
|
397
|
-
errors=None,
|
|
398
|
-
logger=None)
|
|
399
|
-
recipient_attr = registry["recipient-attr"]
|
|
400
|
-
|
|
401
|
-
# validate the token
|
|
402
|
-
if token_validate(token=token,
|
|
403
|
-
issuer=issuer,
|
|
404
|
-
recipient_id=recipient_id,
|
|
405
|
-
recipient_attr=recipient_attr,
|
|
406
|
-
public_key=public_key):
|
|
407
|
-
# token is valid
|
|
408
|
-
bad_token = False
|
|
409
|
-
|
|
410
|
-
# deny the authorization
|
|
411
|
-
if bad_token:
|
|
412
|
-
result = Response(response="Authorization failed",
|
|
413
|
-
status=401)
|
|
414
|
-
return result
|
|
415
|
-
|
|
416
|
-
|
|
417
342
|
def __post_for_token(iam_server: IamServer,
|
|
418
343
|
body_data: dict[str, Any],
|
|
419
344
|
errors: list[str] | None,
|
pypomes_iam/iam_common.py
CHANGED
|
@@ -50,7 +50,7 @@ class IamServer(StrEnum):
|
|
|
50
50
|
# }
|
|
51
51
|
_IAM_SERVERS: Final[dict[IamServer, dict[str, Any]]] = {}
|
|
52
52
|
|
|
53
|
-
# the lock protecting the data in '
|
|
53
|
+
# the lock protecting the data in '_IAM_SERVERS'
|
|
54
54
|
# (because it is 'Final' and set at declaration time, it can be accessed through simple imports)
|
|
55
55
|
_iam_lock: Final[RLock] = RLock()
|
|
56
56
|
|
|
@@ -119,12 +119,39 @@ def _get_public_key(iam_server: IamServer,
|
|
|
119
119
|
"""
|
|
120
120
|
Obtain the public key used by *iam_server* to sign the authentication tokens.
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
This is accomplished by requesting the token issuer for its *JWKS* (JSON Web Key Set),
|
|
123
|
+
containing the public keys used for various purposes, as indicated in the attribute *use*:
|
|
124
|
+
- *enc*: the key is intended for encryption
|
|
125
|
+
- *sig*: the key is intended for digital signature
|
|
126
|
+
- *wrap*: the key is intended for key wrapping
|
|
127
|
+
|
|
128
|
+
A typical JWKS set has the following format (for simplicity, 'n' and 'x5c' are truncated):
|
|
129
|
+
{
|
|
130
|
+
"keys": [
|
|
131
|
+
{
|
|
132
|
+
"kid": "X2QEcSQ4Tg2M2EK6s2nhRHZH_GwD_zxZtiWVwP4S0tg",
|
|
133
|
+
"kty": "RSA",
|
|
134
|
+
"alg": "RSA256",
|
|
135
|
+
"use": "sig",
|
|
136
|
+
"n": "tQmDmyM3tMFt5FMVMbqbQYpaDPf6A5l4e_kTVDBiHrK_bRlGfkk8hYm5SNzNzCZ...",
|
|
137
|
+
"e": "AQAB",
|
|
138
|
+
"x5c": [
|
|
139
|
+
"MIIClzCCAX8CBgGZY0bqrTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARpanVk..."
|
|
140
|
+
],
|
|
141
|
+
"x5t": "MHfVp4kBjEZuYOtiaaGsfLCL15Q",
|
|
142
|
+
"x5t#S256": "QADezSLgD8emuonBz8hn8ghTnxo7AHX4NVNkr4luEhk"
|
|
143
|
+
},
|
|
144
|
+
...
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
Once the signature key is obtained, it is converted from its original *JWK* (JSON Web Key) format
|
|
149
|
+
to *PEM* (Privacy-Enhanced Mail) format. The public key is saved in *iam_server*'s registry.
|
|
123
150
|
|
|
124
151
|
:param iam_server: the reference registered *IAM* server
|
|
125
152
|
:param errors: incidental error messages
|
|
126
153
|
:param logger: optional logger
|
|
127
|
-
:return: the public key in *PEM* format, or *None* if
|
|
154
|
+
:return: the public key in *PEM* format, or *None* if error
|
|
128
155
|
"""
|
|
129
156
|
# initialize the return variable
|
|
130
157
|
result: str | None = None
|
|
@@ -135,9 +162,10 @@ def _get_public_key(iam_server: IamServer,
|
|
|
135
162
|
if registry:
|
|
136
163
|
now: int = int(datetime.now(tz=TZ_LOCAL).timestamp())
|
|
137
164
|
if now > registry["pk-expiration"]:
|
|
138
|
-
# obtain
|
|
165
|
+
# obtain the JWKS (JSON Web Key Set) from the token issuer
|
|
139
166
|
url: str = f"{registry["base-url"]}/protocol/openid-connect/certs"
|
|
140
167
|
if logger:
|
|
168
|
+
logger.debug(msg=f"Obtaining signature public key used by IAM server '{iam_server}'")
|
|
141
169
|
logger.debug(msg=f"GET {url}")
|
|
142
170
|
try:
|
|
143
171
|
response: requests.Response = requests.get(url=url)
|
|
@@ -145,12 +173,29 @@ def _get_public_key(iam_server: IamServer,
|
|
|
145
173
|
# request succeeded
|
|
146
174
|
if logger:
|
|
147
175
|
logger.debug(msg=f"GET success, status {response.status_code}")
|
|
176
|
+
# select the appropriate JWK
|
|
148
177
|
reply: dict[str, Any] = response.json()
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
178
|
+
jwk: dict[str, str] | None = None
|
|
179
|
+
# replay["keys"]: list[dict[str, str]]
|
|
180
|
+
for key in reply["keys"]:
|
|
181
|
+
if key.get("use") == "sig":
|
|
182
|
+
jwk = key
|
|
183
|
+
break
|
|
184
|
+
if jwk:
|
|
185
|
+
# convert from 'JWK' to 'PEM' and save it for further use
|
|
186
|
+
result = crypto_jwk_convert(jwk=jwk,
|
|
187
|
+
fmt="PEM")
|
|
188
|
+
registry["public-key"] = result
|
|
189
|
+
lifetime: int = registry["pk-lifetime"] or 0
|
|
190
|
+
registry["pk-expiration"] = now + lifetime if lifetime else sys.maxsize
|
|
191
|
+
if logger:
|
|
192
|
+
logger.debug(f"Public key obtained and saved")
|
|
193
|
+
else:
|
|
194
|
+
msg = "Signature public key missing from the token issuer's JWKS"
|
|
195
|
+
if logger:
|
|
196
|
+
logger.error(msg=msg)
|
|
197
|
+
if isinstance(errors, list):
|
|
198
|
+
errors.append(msg)
|
|
154
199
|
elif logger:
|
|
155
200
|
msg: str = f"GET failure, status {response.status_code}, reason {response.reason}"
|
|
156
201
|
if hasattr(response, "content") and response.content:
|
pypomes_iam/iam_services.py
CHANGED
|
@@ -3,17 +3,102 @@ from flask import Request, Response, request, jsonify
|
|
|
3
3
|
from logging import Logger
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
|
-
from .iam_common import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
from .iam_common import (
|
|
7
|
+
IamServer, _iam_lock,
|
|
8
|
+
_get_iam_registry, _get_public_key,
|
|
9
|
+
_iam_server_from_endpoint, _iam_server_from_issuer
|
|
10
10
|
)
|
|
11
|
+
from .iam_actions import (
|
|
12
|
+
action_login, action_logout,
|
|
13
|
+
action_token, action_exchange, action_callback
|
|
14
|
+
)
|
|
15
|
+
from .token_pomes import token_get_claims, token_validate
|
|
11
16
|
|
|
12
17
|
# the logger for IAM service operations
|
|
13
18
|
# (used exclusively at the HTTP endpoints - all other functions receive the logger as parameter)
|
|
14
19
|
__IAM_LOGGER: Logger | None = None
|
|
15
20
|
|
|
16
21
|
|
|
22
|
+
def jwt_required(func: callable) -> callable:
|
|
23
|
+
"""
|
|
24
|
+
Create a decorator to authenticate service endpoints with JWT tokens.
|
|
25
|
+
|
|
26
|
+
:param func: the function being decorated
|
|
27
|
+
"""
|
|
28
|
+
# ruff: noqa: ANN003 - Missing type annotation for *{name}
|
|
29
|
+
def wrapper(*args, **kwargs) -> Response:
|
|
30
|
+
response: Response = __request_validate(request=request)
|
|
31
|
+
return response if response else func(*args, **kwargs)
|
|
32
|
+
|
|
33
|
+
# prevent a rogue error ("View function mapping is overwriting an existing endpoint function")
|
|
34
|
+
wrapper.__name__ = func.__name__
|
|
35
|
+
|
|
36
|
+
return wrapper
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __request_validate(request: Request) -> Response:
|
|
40
|
+
"""
|
|
41
|
+
Verify whether the HTTP *request* has the proper authorization, as per the JWT standard.
|
|
42
|
+
|
|
43
|
+
This implementation assumes that HTTP requests are handled with the *Flask* framework.
|
|
44
|
+
Because this code has a high usage frequency, only authentication failures are logged.
|
|
45
|
+
|
|
46
|
+
:param request: the *request* to be verified
|
|
47
|
+
:return: *None* if the *request* is valid, otherwise a *Response* reporting the error
|
|
48
|
+
"""
|
|
49
|
+
# initialize the return variable
|
|
50
|
+
result: Response | None = None
|
|
51
|
+
|
|
52
|
+
# retrieve the authorization from the request header
|
|
53
|
+
auth_header: str = request.headers.get("Authorization")
|
|
54
|
+
|
|
55
|
+
# validate the authorization token
|
|
56
|
+
bad_token: bool = True
|
|
57
|
+
if auth_header and auth_header.startswith("Bearer "):
|
|
58
|
+
# extract and validate the JWT access token
|
|
59
|
+
token: str = auth_header.split(" ")[1]
|
|
60
|
+
claims: dict[str, Any] = token_get_claims(token=token)
|
|
61
|
+
if claims:
|
|
62
|
+
issuer: str = claims["payload"].get("iss")
|
|
63
|
+
recipient_attr: str | None = None
|
|
64
|
+
recipient_id: str = request.values.get("user-id") or request.values.get("login")
|
|
65
|
+
with _iam_lock:
|
|
66
|
+
iam_server: IamServer = _iam_server_from_issuer(issuer=issuer,
|
|
67
|
+
errors=None,
|
|
68
|
+
logger=__IAM_LOGGER)
|
|
69
|
+
if iam_server:
|
|
70
|
+
# validate the token's recipient only if a user identification is provided
|
|
71
|
+
if recipient_id:
|
|
72
|
+
registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
|
|
73
|
+
errors=None,
|
|
74
|
+
logger=__IAM_LOGGER)
|
|
75
|
+
if registry:
|
|
76
|
+
recipient_attr = registry["recipient-attr"]
|
|
77
|
+
public_key: str = _get_public_key(iam_server=iam_server,
|
|
78
|
+
errors=None,
|
|
79
|
+
logger=__IAM_LOGGER)
|
|
80
|
+
# validate the token (log errors, only)
|
|
81
|
+
errors: list[str] = []
|
|
82
|
+
if public_key and token_validate(token=token,
|
|
83
|
+
issuer=issuer,
|
|
84
|
+
recipient_id=recipient_id,
|
|
85
|
+
recipient_attr=recipient_attr,
|
|
86
|
+
public_key=public_key,
|
|
87
|
+
errors=errors):
|
|
88
|
+
# token is valid
|
|
89
|
+
bad_token = False
|
|
90
|
+
elif __IAM_LOGGER:
|
|
91
|
+
__IAM_LOGGER.error("; ".join(errors))
|
|
92
|
+
if bad_token and __IAM_LOGGER:
|
|
93
|
+
__IAM_LOGGER.error(f"authorization refused for token {token}")
|
|
94
|
+
|
|
95
|
+
# deny the authorization
|
|
96
|
+
if bad_token:
|
|
97
|
+
result = Response(response="Authorization failed",
|
|
98
|
+
status=401)
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
|
|
17
102
|
def logger_register(logger: Logger) -> None:
|
|
18
103
|
"""
|
|
19
104
|
Register the logger for HTTP services.
|
|
@@ -60,10 +145,10 @@ def service_login() -> Response:
|
|
|
60
145
|
logger=__IAM_LOGGER)
|
|
61
146
|
if iam_server:
|
|
62
147
|
# obtain the login URL
|
|
63
|
-
login_url: str =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
148
|
+
login_url: str = action_login(iam_server=iam_server,
|
|
149
|
+
args=request.args,
|
|
150
|
+
errors=errors,
|
|
151
|
+
logger=__IAM_LOGGER)
|
|
67
152
|
if login_url:
|
|
68
153
|
result = jsonify({"login-url": login_url})
|
|
69
154
|
if errors:
|
|
@@ -106,10 +191,10 @@ def service_logout() -> Response:
|
|
|
106
191
|
logger=__IAM_LOGGER)
|
|
107
192
|
if iam_server:
|
|
108
193
|
# logout the user
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
194
|
+
action_logout(iam_server=iam_server,
|
|
195
|
+
args=request.args,
|
|
196
|
+
errors=errors,
|
|
197
|
+
logger=__IAM_LOGGER)
|
|
113
198
|
if errors:
|
|
114
199
|
result = Response(response="; ".join(errors),
|
|
115
200
|
status=400)
|
|
@@ -160,10 +245,10 @@ def service_callback() -> Response:
|
|
|
160
245
|
logger=__IAM_LOGGER)
|
|
161
246
|
if iam_server:
|
|
162
247
|
# process the callback operation
|
|
163
|
-
token_data =
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
248
|
+
token_data = action_callback(iam_server=iam_server,
|
|
249
|
+
args=request.args,
|
|
250
|
+
errors=errors,
|
|
251
|
+
logger=__IAM_LOGGER)
|
|
167
252
|
result: Response
|
|
168
253
|
if errors:
|
|
169
254
|
result = jsonify({"errors": "; ".join(errors)})
|
|
@@ -215,10 +300,10 @@ def service_token() -> Response:
|
|
|
215
300
|
if iam_server:
|
|
216
301
|
# retrieve the token
|
|
217
302
|
errors: list[str] = []
|
|
218
|
-
token: str =
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
303
|
+
token: str = action_token(iam_server=iam_server,
|
|
304
|
+
args=args,
|
|
305
|
+
errors=errors,
|
|
306
|
+
logger=__IAM_LOGGER)
|
|
222
307
|
else:
|
|
223
308
|
msg: str = "User identification not provided"
|
|
224
309
|
errors.append(msg)
|
|
@@ -278,10 +363,10 @@ def service_exchange() -> Response:
|
|
|
278
363
|
token_data: dict[str, Any] | None = None
|
|
279
364
|
if iam_server:
|
|
280
365
|
errors: list[str] = []
|
|
281
|
-
token_data =
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
366
|
+
token_data = action_exchange(iam_server=iam_server,
|
|
367
|
+
args=request.args,
|
|
368
|
+
errors=errors,
|
|
369
|
+
logger=__IAM_LOGGER)
|
|
285
370
|
result: Response
|
|
286
371
|
if errors:
|
|
287
372
|
result = Response(response="; ".join(errors),
|
pypomes_iam/jusbr_pomes.py
CHANGED
|
@@ -7,7 +7,7 @@ from pypomes_core import (
|
|
|
7
7
|
from typing import Any, Final
|
|
8
8
|
|
|
9
9
|
from .iam_common import _IAM_SERVERS, IamServer, _iam_lock
|
|
10
|
-
from .
|
|
10
|
+
from .iam_actions import action_token
|
|
11
11
|
|
|
12
12
|
JUSBR_CLIENT_ID: Final[str] = env_get_str(key=f"{APP_PREFIX}_JUSBR_CLIENT_ID")
|
|
13
13
|
JUSBR_CLIENT_SECRET: Final[str] = env_get_str(key=f"{APP_PREFIX}_JUSBR_CLIENT_SECRET")
|
|
@@ -118,8 +118,8 @@ def jusbr_get_token(user_id: str,
|
|
|
118
118
|
# retrieve the token
|
|
119
119
|
args: dict[str, Any] = {"user-id": user_id}
|
|
120
120
|
with _iam_lock:
|
|
121
|
-
result =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
result = action_token(iam_server=IamServer.IAM_JUSRBR,
|
|
122
|
+
args=args,
|
|
123
|
+
errors=errors,
|
|
124
|
+
logger=logger)
|
|
125
125
|
return result
|
pypomes_iam/keycloak_pomes.py
CHANGED
|
@@ -7,7 +7,7 @@ from pypomes_core import (
|
|
|
7
7
|
from typing import Any, Final
|
|
8
8
|
|
|
9
9
|
from .iam_common import _IAM_SERVERS, IamServer, _iam_lock
|
|
10
|
-
from .
|
|
10
|
+
from .iam_actions import action_token
|
|
11
11
|
|
|
12
12
|
KEYCLOAK_CLIENT_ID: Final[str] = env_get_str(key=f"{APP_PREFIX}_KEYCLOAK_CLIENT_ID")
|
|
13
13
|
KEYCLOAK_CLIENT_SECRET: Final[str] = env_get_str(key=f"{APP_PREFIX}_KEYCLOAK_CLIENT_SECRET")
|
|
@@ -129,8 +129,8 @@ def keycloak_get_token(user_id: str,
|
|
|
129
129
|
# retrieve the token
|
|
130
130
|
args: dict[str, Any] = {"user-id": user_id}
|
|
131
131
|
with _iam_lock:
|
|
132
|
-
result =
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
result = action_token(iam_server=IamServer.IAM_KEYCLOAK,
|
|
133
|
+
args=args,
|
|
134
|
+
errors=errors,
|
|
135
|
+
logger=logger)
|
|
136
136
|
return result
|
pypomes_iam/provider_pomes.py
CHANGED
|
@@ -5,7 +5,7 @@ from base64 import b64encode
|
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from logging import Logger
|
|
7
7
|
from pypomes_core import TZ_LOCAL, exc_format
|
|
8
|
-
from threading import
|
|
8
|
+
from threading import Lock
|
|
9
9
|
from typing import Any, Final
|
|
10
10
|
|
|
11
11
|
# structure:
|
|
@@ -25,7 +25,7 @@ _provider_registry: Final[dict[str, dict[str, Any]]] = {}
|
|
|
25
25
|
|
|
26
26
|
# the lock protecting the data in '_provider_registry'
|
|
27
27
|
# (because it is 'Final' and set at declaration time, it can be accessed through simple imports)
|
|
28
|
-
_provider_lock: Final[
|
|
28
|
+
_provider_lock: Final[Lock] = Lock()
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def provider_register(provider_id: str,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pypomes_iam
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.7
|
|
4
4
|
Summary: A collection of Python pomes, penyeach (IAM modules)
|
|
5
5
|
Project-URL: Homepage, https://github.com/TheWiseCoder/PyPomes-IAM
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/TheWiseCoder/PyPomes-IAM/issues
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
pypomes_iam/__init__.py,sha256=GwGK4486tfVD47a4FDiIG6Xl2UeZAKqWUNDauolQNao,1125
|
|
2
|
+
pypomes_iam/iam_actions.py,sha256=0x5kPaDor2rHiOznyF9DLzsNRGLleB66K6RJBPaJkBc,24178
|
|
3
|
+
pypomes_iam/iam_common.py,sha256=yHkbGZb-bSa3sq4UHs1GW4R4474BPTItVm9-J3dd3Bc,12712
|
|
4
|
+
pypomes_iam/iam_services.py,sha256=iq0BQ4sHikPJPiVMv3-q6cYfZVSCxauVkpQilaiSUR8,15783
|
|
5
|
+
pypomes_iam/jusbr_pomes.py,sha256=X_YgY45122tflAzQdAMEcEyVbPvzFigjHLal0qL1v_M,5916
|
|
6
|
+
pypomes_iam/keycloak_pomes.py,sha256=FGdkPjVGEDp5Pwfav4EIc9uSbT4_pG7oPqaiHeJBSLU,6763
|
|
7
|
+
pypomes_iam/provider_pomes.py,sha256=CdEjYjepGXsehn_ujljUQKs0Ws7xNOzBYG6wKp9C7-E,7233
|
|
8
|
+
pypomes_iam/token_pomes.py,sha256=Bz9pT2oU6jTEr_ZEZEJ3kUjH3TfxRyY1_vR319v6CEo,6692
|
|
9
|
+
pypomes_iam-0.5.7.dist-info/METADATA,sha256=tX2E2pV3KcLsdMOH6YJpL6DYQyfdVcg1iA1tI2O5cpk,694
|
|
10
|
+
pypomes_iam-0.5.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
+
pypomes_iam-0.5.7.dist-info/licenses/LICENSE,sha256=YvUELgV8qvXlaYsy9hXG5EW3Bmsrkw-OJmmILZnonAc,1086
|
|
12
|
+
pypomes_iam-0.5.7.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
pypomes_iam/__init__.py,sha256=KX_QLdqAD-dNUl3G1mDeutxL9e58S9OsMoJlrgM9R28,1027
|
|
2
|
-
pypomes_iam/iam_common.py,sha256=xRMVPIDxbVPoudPDKFCqGCA7Klt9HsZM61dSGfEy7Tw,10364
|
|
3
|
-
pypomes_iam/iam_pomes.py,sha256=sB2DDCaN5nN6ehZH4HCsWxPM9IbP5IRt42UhIRtn07Q,27436
|
|
4
|
-
pypomes_iam/iam_services.py,sha256=fdpOc6EmCLcMtkhZU5OX9gYJIA1RNyM3JcoMX0RqwXA,11829
|
|
5
|
-
pypomes_iam/jusbr_pomes.py,sha256=cuQWB5OTeAHarmUqAGIU4udSEJA1C6W6lOtauWA7gqw,5904
|
|
6
|
-
pypomes_iam/keycloak_pomes.py,sha256=OvPhfUXpqxll-p6CdRq2j5jp5ST9Z0feXg6TVbqC2cY,6751
|
|
7
|
-
pypomes_iam/provider_pomes.py,sha256=EFgWZO7kdUVJ5_z8egdzG9nmmpa7wTXOyo9Ops5NAEE,7236
|
|
8
|
-
pypomes_iam/token_pomes.py,sha256=Bz9pT2oU6jTEr_ZEZEJ3kUjH3TfxRyY1_vR319v6CEo,6692
|
|
9
|
-
pypomes_iam-0.5.5.dist-info/METADATA,sha256=FvKoV08gCZ-WvswVzMMlEOFi6jPlNZba7zUPeLtIVLU,694
|
|
10
|
-
pypomes_iam-0.5.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
-
pypomes_iam-0.5.5.dist-info/licenses/LICENSE,sha256=YvUELgV8qvXlaYsy9hXG5EW3Bmsrkw-OJmmILZnonAc,1086
|
|
12
|
-
pypomes_iam-0.5.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|