pypomes-iam 0.8.5__py3-none-any.whl → 0.8.9__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.
- pypomes_iam/__init__.py +7 -5
- pypomes_iam/iam_actions.py +32 -33
- pypomes_iam/iam_common.py +36 -41
- pypomes_iam/iam_pomes.py +20 -20
- pypomes_iam/iam_services.py +9 -9
- pypomes_iam/provider_pomes.py +41 -36
- {pypomes_iam-0.8.5.dist-info → pypomes_iam-0.8.9.dist-info}/METADATA +1 -1
- pypomes_iam-0.8.9.dist-info/RECORD +11 -0
- pypomes_iam-0.8.5.dist-info/RECORD +0 -11
- {pypomes_iam-0.8.5.dist-info → pypomes_iam-0.8.9.dist-info}/WHEEL +0 -0
- {pypomes_iam-0.8.5.dist-info → pypomes_iam-0.8.9.dist-info}/licenses/LICENSE +0 -0
pypomes_iam/__init__.py
CHANGED
|
@@ -3,7 +3,7 @@ from .iam_actions import (
|
|
|
3
3
|
iam_login, iam_logout, iam_get_token, iam_userinfo
|
|
4
4
|
)
|
|
5
5
|
from .iam_common import (
|
|
6
|
-
IamServer,
|
|
6
|
+
IamServer, ServerParam
|
|
7
7
|
)
|
|
8
8
|
from .iam_pomes import (
|
|
9
9
|
iam_setup_server, iam_setup_endpoints
|
|
@@ -15,8 +15,9 @@ from .iam_services import (
|
|
|
15
15
|
service_exchange, service_callback_exchange
|
|
16
16
|
)
|
|
17
17
|
from .provider_pomes import (
|
|
18
|
+
IamProvider, ProviderParam,
|
|
18
19
|
service_get_token, provider_get_token,
|
|
19
|
-
provider_setup_endpoint, provider_setup_logger
|
|
20
|
+
iam_setup_provider, provider_setup_endpoint, provider_setup_logger
|
|
20
21
|
)
|
|
21
22
|
from .token_pomes import (
|
|
22
23
|
token_get_claims, token_get_values, token_validate
|
|
@@ -27,7 +28,7 @@ __all__ = [
|
|
|
27
28
|
"iam_callback", "iam_exchange",
|
|
28
29
|
"iam_login", "iam_logout", "iam_get_token", "iam_userinfo",
|
|
29
30
|
# iam_commons
|
|
30
|
-
"IamServer", "
|
|
31
|
+
"IamServer", "ServerParam",
|
|
31
32
|
# iam_pomes
|
|
32
33
|
"iam_setup_server", "iam_setup_endpoints",
|
|
33
34
|
# iam_services
|
|
@@ -36,8 +37,9 @@ __all__ = [
|
|
|
36
37
|
"service_get_token", "service_userinfo", "service_callback",
|
|
37
38
|
"service_exchange", "service_callback_exchange",
|
|
38
39
|
# provider_pomes
|
|
39
|
-
"
|
|
40
|
-
"
|
|
40
|
+
"IamProvider", "ProviderParam",
|
|
41
|
+
"service_get_token", "provider_get_token",
|
|
42
|
+
"iam_setup_provider", "provider_setup_endpoint", "provider_setup_logger",
|
|
41
43
|
# token_pomes
|
|
42
44
|
"token_get_claims", "token_get_values", "token_validate"
|
|
43
45
|
]
|
pypomes_iam/iam_actions.py
CHANGED
|
@@ -9,7 +9,7 @@ from pypomes_core import TZ_LOCAL, exc_format
|
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
11
|
from .iam_common import (
|
|
12
|
-
IamServer,
|
|
12
|
+
IamServer, ServerParam, UserParam, _iam_lock,
|
|
13
13
|
_get_iam_users, _get_iam_registry, _get_public_key,
|
|
14
14
|
_get_login_timeout, _get_user_data, _iam_server_from_issuer
|
|
15
15
|
)
|
|
@@ -56,7 +56,7 @@ def iam_login(iam_server: IamServer,
|
|
|
56
56
|
# ('oauth_state' is a randomly-generated string, thus 'user_data' is always a new entry)
|
|
57
57
|
oauth_state: str = "".join(secrets.choice(string.ascii_letters + string.digits) for _ in range(16))
|
|
58
58
|
if target_idp:
|
|
59
|
-
oauth_state += f"
|
|
59
|
+
oauth_state += f"_{target_idp}"
|
|
60
60
|
|
|
61
61
|
with _iam_lock:
|
|
62
62
|
# retrieve the user data from the IAM server's registry
|
|
@@ -80,10 +80,10 @@ def iam_login(iam_server: IamServer,
|
|
|
80
80
|
errors=errors,
|
|
81
81
|
logger=logger)
|
|
82
82
|
if registry:
|
|
83
|
-
base_url: str = f"{registry[
|
|
83
|
+
base_url: str = f"{registry[ServerParam.URL_BASE]}/realms/{registry[ServerParam.CLIENT_REALM]}"
|
|
84
84
|
result = (f"{base_url}/protocol/openid-connect/auth"
|
|
85
85
|
f"?response_type=code&scope=openid"
|
|
86
|
-
f"&client_id={registry[
|
|
86
|
+
f"&client_id={registry[ServerParam.CLIENT_ID]}"
|
|
87
87
|
f"&redirect_uri={redirect_uri}"
|
|
88
88
|
f"&state={oauth_state}")
|
|
89
89
|
if target_idp:
|
|
@@ -118,7 +118,7 @@ def iam_logout(iam_server: IamServer,
|
|
|
118
118
|
registry: dict[str, Any] = _get_iam_registry(iam_server,
|
|
119
119
|
errors=errors,
|
|
120
120
|
logger=logger)
|
|
121
|
-
users: dict[str, dict[str, Any]] = registry[
|
|
121
|
+
users: dict[str, dict[str, Any]] = registry[ServerParam.USERS] if registry else {}
|
|
122
122
|
user_data: dict[str, Any] = users.get(user_id)
|
|
123
123
|
if user_data:
|
|
124
124
|
# request the IAM server to logout 'client_id'
|
|
@@ -126,13 +126,13 @@ def iam_logout(iam_server: IamServer,
|
|
|
126
126
|
errors=errors,
|
|
127
127
|
logger=logger)
|
|
128
128
|
if client_secret:
|
|
129
|
-
url: str = (f"{registry[
|
|
129
|
+
url: str = (f"{registry[ServerParam.URL_BASE]}/realms/{registry[ServerParam.CLIENT_REALM]}"
|
|
130
130
|
"/protocol/openid-connect/logout")
|
|
131
131
|
header_data: dict[str, str] = {
|
|
132
132
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
133
133
|
}
|
|
134
134
|
body_data: dict[str, Any] = {
|
|
135
|
-
"client_id": registry[
|
|
135
|
+
"client_id": registry[ServerParam.CLIENT_ID],
|
|
136
136
|
"client_secret": client_secret,
|
|
137
137
|
"refresh_token": user_data[UserParam.REFRESH_TOKEN]
|
|
138
138
|
}
|
|
@@ -322,9 +322,9 @@ def iam_callback(iam_server: IamServer,
|
|
|
322
322
|
if int(datetime.now(tz=TZ_LOCAL).timestamp()) > expiration:
|
|
323
323
|
errors.append("Operation timeout")
|
|
324
324
|
else:
|
|
325
|
-
pos: int = oauth_state.rfind("
|
|
326
|
-
target_idp: str = oauth_state[pos+
|
|
327
|
-
target_iam = IamServer(target_idp) if target_idp in IamServer else None
|
|
325
|
+
pos: int = oauth_state.rfind("_")
|
|
326
|
+
target_idp: str = oauth_state[pos+1:] if pos > 0 else None
|
|
327
|
+
target_iam: IamServer = IamServer(target_idp) if target_idp in IamServer else None
|
|
328
328
|
target_data: dict[str, Any] = user_data.copy() if target_iam else None
|
|
329
329
|
users.pop(oauth_state)
|
|
330
330
|
code: str = args.get("code")
|
|
@@ -357,8 +357,8 @@ def iam_callback(iam_server: IamServer,
|
|
|
357
357
|
registry: dict[str, Any] = _get_iam_registry(iam_server,
|
|
358
358
|
errors=errors,
|
|
359
359
|
logger=logger)
|
|
360
|
-
url: str = (f"{registry[
|
|
361
|
-
f"{registry[
|
|
360
|
+
url: str = (f"{registry[ServerParam.URL_BASE]}/realms/"
|
|
361
|
+
f"{registry[ServerParam.CLIENT_REALM]}/broker/{target_idp}/token")
|
|
362
362
|
header_data: dict[str, str] = {
|
|
363
363
|
"Authorization": f"Bearer {result[1]}",
|
|
364
364
|
"Content-Type": "application/json"
|
|
@@ -426,7 +426,6 @@ def iam_exchange(iam_server: IamServer,
|
|
|
426
426
|
errors=errors,
|
|
427
427
|
logger=logger)
|
|
428
428
|
if not errors:
|
|
429
|
-
# HAZARD: only 'IAM_KEYCLOAK' is currently supported
|
|
430
429
|
with _iam_lock:
|
|
431
430
|
# retrieve the IAM server's registry
|
|
432
431
|
registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
|
|
@@ -452,7 +451,7 @@ def iam_exchange(iam_server: IamServer,
|
|
|
452
451
|
"subject_token": token,
|
|
453
452
|
"subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
|
|
454
453
|
"requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
|
|
455
|
-
"audience": registry[
|
|
454
|
+
"audience": registry[ServerParam.CLIENT_ID],
|
|
456
455
|
"subject_issuer": token_issuer
|
|
457
456
|
}
|
|
458
457
|
now: int = int(datetime.now(tz=TZ_LOCAL).timestamp())
|
|
@@ -508,9 +507,9 @@ def iam_userinfo(iam_server: IamServer,
|
|
|
508
507
|
registry: dict[str, Any] = _get_iam_registry(iam_server,
|
|
509
508
|
errors=errors,
|
|
510
509
|
logger=logger)
|
|
511
|
-
user_data: dict[str, Any] = registry[
|
|
510
|
+
user_data: dict[str, Any] = registry[ServerParam.USERS].get(user_id)
|
|
512
511
|
if user_data:
|
|
513
|
-
url: str = (f"{registry[
|
|
512
|
+
url: str = (f"{registry[ServerParam.URL_BASE]}/realms/{registry[ServerParam.CLIENT_REALM]}"
|
|
514
513
|
"/protocol/openid-connect/userinfo")
|
|
515
514
|
header_data: dict[str, str] = {
|
|
516
515
|
"Authorization": f"Bearer {args.get('access-token')}"
|
|
@@ -566,7 +565,7 @@ def __assert_link(iam_server: IamServer,
|
|
|
566
565
|
if logger:
|
|
567
566
|
logger.debug(msg="Obtaining internal identification "
|
|
568
567
|
f"for user '{user_id}' in IAM server '{iam_server}'")
|
|
569
|
-
url: str = f"{registry[
|
|
568
|
+
url: str = f"{registry[ServerParam.URL_BASE]}/admin/realms/{registry[ServerParam.CLIENT_REALM]}/users"
|
|
570
569
|
header_data: dict[str, str] = {
|
|
571
570
|
"Authorization": f"Bearer {admin_token}",
|
|
572
571
|
"Content-Type": "application/json"
|
|
@@ -587,8 +586,8 @@ def __assert_link(iam_server: IamServer,
|
|
|
587
586
|
if logger:
|
|
588
587
|
logger.debug(msg="Obtaining the providers federated in IAM server "
|
|
589
588
|
f"'{iam_server}', for internal identification '{internal_id}'")
|
|
590
|
-
url = (f"{registry[
|
|
591
|
-
f"{registry[
|
|
589
|
+
url = (f"{registry[ServerParam.URL_BASE]}/admin/realms/"
|
|
590
|
+
f"{registry[ServerParam.CLIENT_REALM]}/users/{internal_id}/federated-identity")
|
|
592
591
|
providers: list[dict[str, Any]] = __get_for_data(url=url,
|
|
593
592
|
header_data=header_data,
|
|
594
593
|
params=None,
|
|
@@ -651,14 +650,14 @@ def __get_administrative_token(iam_server: IamServer,
|
|
|
651
650
|
errors=errors,
|
|
652
651
|
logger=logger)
|
|
653
652
|
if registry:
|
|
654
|
-
if registry[
|
|
653
|
+
if registry[ServerParam.ADMIN_ID] and registry[ServerParam.ADMIN_SECRET]:
|
|
655
654
|
header_data: dict[str, str] = {
|
|
656
655
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
657
656
|
}
|
|
658
657
|
body_data: dict[str, str] = {
|
|
659
658
|
"grant_type": "password",
|
|
660
|
-
"username": registry[
|
|
661
|
-
"password": registry[
|
|
659
|
+
"username": registry[ServerParam.ADMIN_ID],
|
|
660
|
+
"password": registry[ServerParam.ADMIN_SECRET],
|
|
662
661
|
"client_id": "admin-cli"
|
|
663
662
|
}
|
|
664
663
|
token_data: dict[str, Any] = __post_for_token(iam_server=iam_server,
|
|
@@ -674,7 +673,7 @@ def __get_administrative_token(iam_server: IamServer,
|
|
|
674
673
|
|
|
675
674
|
elif logger or isinstance(errors, list):
|
|
676
675
|
msg: str = ("Credentials for administrator of realm "
|
|
677
|
-
f"'{registry[
|
|
676
|
+
f"'{registry[ServerParam.CLIENT_REALM]}' "
|
|
678
677
|
f"at IAM server '{iam_server}' not provided")
|
|
679
678
|
if logger:
|
|
680
679
|
logger.error(msg=msg)
|
|
@@ -710,7 +709,7 @@ def __get_client_secret(iam_server: IamServer,
|
|
|
710
709
|
registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
|
|
711
710
|
errors=errors,
|
|
712
711
|
logger=logger)
|
|
713
|
-
result: str = registry[
|
|
712
|
+
result: str = registry[ServerParam.CLIENT_SECRET] if registry else None
|
|
714
713
|
|
|
715
714
|
if not result and not errors:
|
|
716
715
|
# obtain a token with administrative rights
|
|
@@ -718,13 +717,13 @@ def __get_client_secret(iam_server: IamServer,
|
|
|
718
717
|
errors=errors,
|
|
719
718
|
logger=logger)
|
|
720
719
|
if token:
|
|
721
|
-
realm: str = registry[
|
|
722
|
-
client_id: str = registry[
|
|
720
|
+
realm: str = registry[ServerParam.CLIENT_REALM]
|
|
721
|
+
client_id: str = registry[ServerParam.CLIENT_ID]
|
|
723
722
|
if logger:
|
|
724
723
|
logger.debug(msg=f"Obtaining the UUID for client '{client_id}', "
|
|
725
724
|
f"in realm '{realm}' at IAM server '{iam_server}'")
|
|
726
725
|
# obtain the client UUID
|
|
727
|
-
url: str = f"{registry[
|
|
726
|
+
url: str = f"{registry[ServerParam.URL_BASE]}/realms/{realm}/clients"
|
|
728
727
|
header_data: dict[str, str] = {
|
|
729
728
|
"Authorization": f"Bearer {token}",
|
|
730
729
|
"Content-Type": "application/json"
|
|
@@ -752,7 +751,7 @@ def __get_client_secret(iam_server: IamServer,
|
|
|
752
751
|
if reply:
|
|
753
752
|
# store the client's secret password and return it
|
|
754
753
|
result = reply["value"]
|
|
755
|
-
registry[
|
|
754
|
+
registry[ServerParam.CLIENT_ID] = result
|
|
756
755
|
return result
|
|
757
756
|
|
|
758
757
|
|
|
@@ -916,11 +915,11 @@ def __post_for_token(iam_server: IamServer,
|
|
|
916
915
|
if registry:
|
|
917
916
|
# complete the data to send in body of request
|
|
918
917
|
if body_data["grant_type"] != "password":
|
|
919
|
-
body_data["client_id"] = registry[
|
|
918
|
+
body_data["client_id"] = registry[ServerParam.CLIENT_ID]
|
|
920
919
|
|
|
921
920
|
# build the URL
|
|
922
|
-
url: str = (f"{registry[
|
|
923
|
-
f"{registry[
|
|
921
|
+
url: str = (f"{registry[ServerParam.URL_BASE]}/realms/"
|
|
922
|
+
f"{registry[ServerParam.CLIENT_REALM]}/protocol/openid-connect/token")
|
|
924
923
|
# 'client_secret' data must not be shown in log
|
|
925
924
|
msg: str = f"POST {url}, {json.dumps(obj=body_data,
|
|
926
925
|
ensure_ascii=False)}"
|
|
@@ -1021,9 +1020,9 @@ def __validate_and_store(iam_server: IamServer,
|
|
|
1021
1020
|
public_key: str = _get_public_key(iam_server=iam_server,
|
|
1022
1021
|
errors=errors,
|
|
1023
1022
|
logger=logger)
|
|
1024
|
-
recipient_attr = registry[
|
|
1023
|
+
recipient_attr = registry[ServerParam.RECIPIENT_ATTR]
|
|
1025
1024
|
login_id = user_data.pop("login-id", None)
|
|
1026
|
-
base_url: str = f"{registry[
|
|
1025
|
+
base_url: str = f"{registry[ServerParam.URL_BASE]}/realms/{registry[ServerParam.CLIENT_REALM]}"
|
|
1027
1026
|
claims: dict[str, dict[str, Any]] = token_validate(token=token,
|
|
1028
1027
|
issuer=base_url,
|
|
1029
1028
|
recipient_id=login_id,
|
pypomes_iam/iam_common.py
CHANGED
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
import sys
|
|
3
3
|
from datetime import datetime
|
|
4
|
-
from enum import StrEnum
|
|
4
|
+
from enum import StrEnum
|
|
5
5
|
from logging import Logger
|
|
6
6
|
from pypomes_core import (
|
|
7
7
|
APP_PREFIX, TZ_LOCAL, exc_format,
|
|
8
|
-
|
|
8
|
+
env_get_int, env_get_str, env_get_strs
|
|
9
9
|
)
|
|
10
10
|
from pypomes_crypto import crypto_jwk_convert
|
|
11
11
|
from threading import RLock
|
|
12
12
|
from typing import Any, Final
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"""
|
|
19
|
-
JUSBR = auto()
|
|
20
|
-
KEYCLOAK = auto()
|
|
14
|
+
_members: dict[str, str] = {key.upper(): key.lower() for key in
|
|
15
|
+
env_get_strs(key=f"{APP_PREFIX}_AUTH_SERVERS")}
|
|
16
|
+
IamServer: type[StrEnum] = StrEnum("IamServer", _members)
|
|
17
|
+
del _members
|
|
21
18
|
|
|
22
19
|
|
|
23
|
-
class
|
|
20
|
+
class ServerParam(StrEnum):
|
|
24
21
|
"""
|
|
25
22
|
Parameters for configuring *IAM* servers.
|
|
26
23
|
"""
|
|
@@ -60,7 +57,7 @@ class UserParam(StrEnum):
|
|
|
60
57
|
REDIRECT_URI = "redirect-uri"
|
|
61
58
|
|
|
62
59
|
|
|
63
|
-
def __get_iam_data() -> dict[IamServer, dict[
|
|
60
|
+
def __get_iam_data() -> dict[IamServer, dict[ServerParam, Any]]:
|
|
64
61
|
"""
|
|
65
62
|
Obtain the configuration data for select *IAM* servers.
|
|
66
63
|
|
|
@@ -69,8 +66,8 @@ def __get_iam_data() -> dict[IamServer, dict[IamParam, Any]]:
|
|
|
69
66
|
variables can be done by following these steps:
|
|
70
67
|
|
|
71
68
|
1. Specify *<APP_PREFIX>_AUTH_SERVERS* with a list of names among the values found in *IamServer* class
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
and the data set below for each server, where *<IAM>* stands for the server's name as presented in
|
|
70
|
+
*IamServer* class:
|
|
74
71
|
- *<APP_PREFIX>_<IAM>_ADMIN_ID* (optional, required if administrative duties are performed)
|
|
75
72
|
- *<APP_PREFIX>_<IAM>_ADMIN_PWD* (optional, required if administrative duties are performed)
|
|
76
73
|
- *<APP_PREFIX>_<IAM>_CLIENT_ID* (required)
|
|
@@ -96,26 +93,24 @@ def __get_iam_data() -> dict[IamServer, dict[IamParam, Any]]:
|
|
|
96
93
|
:return: the configuration data for the select *IAM* servers.
|
|
97
94
|
"""
|
|
98
95
|
# initialize the return variable
|
|
99
|
-
result: dict[IamServer, dict[
|
|
96
|
+
result: dict[IamServer, dict[ServerParam, Any]] = {}
|
|
100
97
|
|
|
101
|
-
|
|
102
|
-
enum_class=IamServer) or []
|
|
103
|
-
for server in servers:
|
|
98
|
+
for server in IamServer:
|
|
104
99
|
prefix = server.name
|
|
105
100
|
result[server] = {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
101
|
+
ServerParam.ADMIN_ID: env_get_str(key=f"{APP_PREFIX}_{prefix}_ADMIN_ID"),
|
|
102
|
+
ServerParam.ADMIN_SECRET: env_get_str(key=f"{APP_PREFIX}_{prefix}_ADMIN_SECRET"),
|
|
103
|
+
ServerParam.CLIENT_ID: env_get_str(key=f"{APP_PREFIX}_{prefix}_CLIENT_ID"),
|
|
104
|
+
ServerParam.CLIENT_REALM: env_get_str(key=f"{APP_PREFIX}_{prefix}_CLIENT_REALM"),
|
|
105
|
+
ServerParam.CLIENT_SECRET: env_get_str(key=f"{APP_PREFIX}_{prefix}_CLIENT_SECRET"),
|
|
106
|
+
ServerParam.LOGIN_TIMEOUT: env_get_str(key=f"{APP_PREFIX}_{prefix}_LOGIN_TIMEOUT"),
|
|
107
|
+
ServerParam.PK_LIFETIME: env_get_int(key=f"{APP_PREFIX}_{prefix}_PK_LIFETIME"),
|
|
108
|
+
ServerParam.RECIPIENT_ATTR: env_get_str(key=f"{APP_PREFIX}_{prefix}_RECIPIENT_ATTR"),
|
|
109
|
+
ServerParam.URL_BASE: env_get_str(key=f"{APP_PREFIX}_{prefix}_URL_BASE"),
|
|
115
110
|
# dynamically set
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
ServerParam.PK_EXPIRATION: 0,
|
|
112
|
+
ServerParam.PUBLIC_KEY: None,
|
|
113
|
+
ServerParam.USERS: {}
|
|
119
114
|
}
|
|
120
115
|
|
|
121
116
|
return result
|
|
@@ -154,7 +149,7 @@ def __get_iam_data() -> dict[IamServer, dict[IamParam, Any]]:
|
|
|
154
149
|
# },
|
|
155
150
|
# ...
|
|
156
151
|
# }
|
|
157
|
-
_IAM_SERVERS: Final[dict[IamServer, dict[
|
|
152
|
+
_IAM_SERVERS: Final[dict[IamServer, dict[ServerParam, Any]]] = __get_iam_data()
|
|
158
153
|
|
|
159
154
|
|
|
160
155
|
# the lock protecting the data in '_<IAM>_SERVERS'
|
|
@@ -174,7 +169,7 @@ def _iam_server_from_endpoint(endpoint: str,
|
|
|
174
169
|
:return: the corresponding *IAM* server, or *None* if one could not be obtained
|
|
175
170
|
"""
|
|
176
171
|
# initialize the return variable
|
|
177
|
-
result: IamServer | None = None
|
|
172
|
+
result: type(IamServer) | None = None
|
|
178
173
|
|
|
179
174
|
for iam_server in _IAM_SERVERS:
|
|
180
175
|
if endpoint.startswith(iam_server):
|
|
@@ -203,12 +198,12 @@ def _iam_server_from_issuer(issuer: str,
|
|
|
203
198
|
:return: the corresponding *IAM* server, or *None* if one could not be obtained
|
|
204
199
|
"""
|
|
205
200
|
# initialize the return variable
|
|
206
|
-
result: IamServer | None = None
|
|
201
|
+
result: type(IamServer) | None = None
|
|
207
202
|
|
|
208
203
|
for iam_server, registry in _IAM_SERVERS.items():
|
|
209
|
-
base_url: str = f"{registry[
|
|
204
|
+
base_url: str = f"{registry[ServerParam.URL_BASE]}/realms/{registry[ServerParam.CLIENT_REALM]}"
|
|
210
205
|
if base_url == issuer:
|
|
211
|
-
result = IamServer(iam_server)
|
|
206
|
+
result = type(IamServer)(iam_server)
|
|
212
207
|
break
|
|
213
208
|
|
|
214
209
|
if not result:
|
|
@@ -269,9 +264,9 @@ def _get_public_key(iam_server: IamServer,
|
|
|
269
264
|
logger=logger)
|
|
270
265
|
if registry:
|
|
271
266
|
now: int = int(datetime.now(tz=TZ_LOCAL).timestamp())
|
|
272
|
-
if now > registry[
|
|
267
|
+
if now > registry[ServerParam.PK_EXPIRATION]:
|
|
273
268
|
# obtain the JWKS (JSON Web Key Set) from the token issuer
|
|
274
|
-
base_url: str = f"{registry[
|
|
269
|
+
base_url: str = f"{registry[ServerParam.URL_BASE]}/realms/{registry[ServerParam.CLIENT_REALM]}"
|
|
275
270
|
url: str = f"{base_url}/protocol/openid-connect/certs"
|
|
276
271
|
if logger:
|
|
277
272
|
logger.debug(msg=f"Obtaining signature public key used by IAM server '{iam_server}'")
|
|
@@ -293,9 +288,9 @@ def _get_public_key(iam_server: IamServer,
|
|
|
293
288
|
# convert from 'JWK' to 'PEM' and save it for further use
|
|
294
289
|
result = crypto_jwk_convert(jwk=jwk,
|
|
295
290
|
fmt="PEM")
|
|
296
|
-
registry[
|
|
297
|
-
lifetime: int = registry[
|
|
298
|
-
registry[
|
|
291
|
+
registry[ServerParam.PUBLIC_KEY] = result
|
|
292
|
+
lifetime: int = registry[ServerParam.PK_LIFETIME] or 0
|
|
293
|
+
registry[ServerParam.PK_EXPIRATION] = now + lifetime if lifetime else sys.maxsize
|
|
299
294
|
if logger:
|
|
300
295
|
logger.debug("Public key obtained and saved")
|
|
301
296
|
else:
|
|
@@ -320,7 +315,7 @@ def _get_public_key(iam_server: IamServer,
|
|
|
320
315
|
if isinstance(errors, list):
|
|
321
316
|
errors.append(msg)
|
|
322
317
|
else:
|
|
323
|
-
result = registry[
|
|
318
|
+
result = registry[ServerParam.PUBLIC_KEY]
|
|
324
319
|
|
|
325
320
|
return result
|
|
326
321
|
|
|
@@ -427,4 +422,4 @@ def _get_iam_users(iam_server: IamServer,
|
|
|
427
422
|
registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
|
|
428
423
|
errors=errors,
|
|
429
424
|
logger=logger)
|
|
430
|
-
return registry[
|
|
425
|
+
return registry[ServerParam.USERS] if registry else None
|
pypomes_iam/iam_pomes.py
CHANGED
|
@@ -6,7 +6,7 @@ from pypomes_core import (
|
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
from .iam_common import (
|
|
9
|
-
_IAM_SERVERS, IamServer,
|
|
9
|
+
_IAM_SERVERS, IamServer, ServerParam, _iam_lock
|
|
10
10
|
)
|
|
11
11
|
from .iam_services import (
|
|
12
12
|
service_login, service_logout,
|
|
@@ -41,7 +41,7 @@ def iam_setup_server(iam_server: IamServer,
|
|
|
41
41
|
it is not provided, but *admin_id* and *admin_secret* are, it is obtained from the *IAM* server itself
|
|
42
42
|
the first time it is needed.
|
|
43
43
|
|
|
44
|
-
:param iam_server: identifies the supported *IAM* server
|
|
44
|
+
:param iam_server: identifies the supported *IAM* server
|
|
45
45
|
:param admin_id: identifies the realm administrator
|
|
46
46
|
:param admin_secret: password for the realm administrator
|
|
47
47
|
:param client_id: the client's identification with the *IAM* server
|
|
@@ -70,28 +70,28 @@ def iam_setup_server(iam_server: IamServer,
|
|
|
70
70
|
if "login_timeout" in defaulted_params:
|
|
71
71
|
login_timeout = env_get_str(key=f"{APP_PREFIX}_{prefix}_LOGIN_TIMEOUT")
|
|
72
72
|
if "pk_lifetime" in defaulted_params:
|
|
73
|
-
pk_lifetime = env_get_int(key=f"{APP_PREFIX}_{prefix}
|
|
73
|
+
pk_lifetime = env_get_int(key=f"{APP_PREFIX}_{prefix}_PK_LIFETIME")
|
|
74
74
|
if "recipient_attr" in defaulted_params:
|
|
75
75
|
recipient_attr = env_get_str(key=f"{APP_PREFIX}_{prefix}_RECIPIENT_ATTR")
|
|
76
76
|
if "url_base" in defaulted_params:
|
|
77
|
-
url_base = env_get_str(key=f"{APP_PREFIX}_{prefix}
|
|
77
|
+
url_base = env_get_str(key=f"{APP_PREFIX}_{prefix}_URL_BASE")
|
|
78
78
|
|
|
79
|
-
# configure the
|
|
79
|
+
# configure the IAM server's registry
|
|
80
80
|
with _iam_lock:
|
|
81
81
|
_IAM_SERVERS[iam_server] = {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
ServerParam.CLIENT_ID: client_id,
|
|
83
|
+
ServerParam.CLIENT_REALM: client_realm,
|
|
84
|
+
ServerParam.CLIENT_SECRET: client_secret,
|
|
85
|
+
ServerParam.RECIPIENT_ATTR: recipient_attr,
|
|
86
|
+
ServerParam.ADMIN_ID: admin_id,
|
|
87
|
+
ServerParam.ADMIN_SECRET: admin_secret,
|
|
88
|
+
ServerParam.LOGIN_TIMEOUT: login_timeout,
|
|
89
|
+
ServerParam.PK_LIFETIME: pk_lifetime,
|
|
90
|
+
ServerParam.URL_BASE: url_base,
|
|
91
91
|
# dynamic attributes
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
ServerParam.PK_EXPIRATION: 0,
|
|
93
|
+
ServerParam.PUBLIC_KEY: None,
|
|
94
|
+
ServerParam.USERS: {}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
|
|
@@ -112,7 +112,7 @@ def iam_setup_endpoints(flask_app: Flask,
|
|
|
112
112
|
environment variables.
|
|
113
113
|
|
|
114
114
|
:param flask_app: the Flask application
|
|
115
|
-
:param iam_server: identifies the supported *IAM* server
|
|
115
|
+
:param iam_server: identifies the supported *IAM* server
|
|
116
116
|
:param callback_endpoint: endpoint for the callback from the front end
|
|
117
117
|
:param callback_exchange_endpoint: endpoint for the combination callback and exchange
|
|
118
118
|
:param exchange_endpoint: endpoint for requesting token exchange
|
|
@@ -131,7 +131,7 @@ def iam_setup_endpoints(flask_app: Flask,
|
|
|
131
131
|
if "callback_exchange_endpoint" in defaulted_params:
|
|
132
132
|
callback_exchange_endpoint = env_get_str(key=f"{APP_PREFIX}_{prefix}_ENDPOINT_CALLBACK_EXCHANGE")
|
|
133
133
|
if "exchange_endpoint" in defaulted_params:
|
|
134
|
-
|
|
134
|
+
exchange_endpoint = env_get_str(key=f"{APP_PREFIX}_{prefix}_ENDPOINT_EXCHANGE")
|
|
135
135
|
if "login_endpoint" in defaulted_params:
|
|
136
136
|
login_endpoint = env_get_str(key=f"{APP_PREFIX}_{prefix}_ENDPOINT_LOGIN")
|
|
137
137
|
if "logout_endpoint" in defaulted_params:
|
|
@@ -146,7 +146,7 @@ def iam_setup_endpoints(flask_app: Flask,
|
|
|
146
146
|
flask_app.add_url_rule(rule=callback_endpoint,
|
|
147
147
|
endpoint=f"{iam_server}-callback",
|
|
148
148
|
view_func=service_callback,
|
|
149
|
-
methods=["GET"])
|
|
149
|
+
methods=["GET", "POST"])
|
|
150
150
|
if callback_exchange_endpoint:
|
|
151
151
|
flask_app.add_url_rule(rule=callback_exchange_endpoint,
|
|
152
152
|
endpoint=f"{iam_server}-callback-exchange",
|
pypomes_iam/iam_services.py
CHANGED
|
@@ -4,7 +4,7 @@ from logging import Logger
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
6
|
from .iam_common import (
|
|
7
|
-
IamServer,
|
|
7
|
+
IamServer, ServerParam, _iam_lock,
|
|
8
8
|
_get_iam_registry, _get_public_key,
|
|
9
9
|
_iam_server_from_endpoint, _iam_server_from_issuer
|
|
10
10
|
)
|
|
@@ -74,7 +74,7 @@ def __request_validate(request: Request) -> Response:
|
|
|
74
74
|
errors=None,
|
|
75
75
|
logger=__IAM_LOGGER)
|
|
76
76
|
if registry:
|
|
77
|
-
recipient_attr = registry[
|
|
77
|
+
recipient_attr = registry[ServerParam.RECIPIENT_ATTR]
|
|
78
78
|
public_key = _get_public_key(iam_server=iam_server,
|
|
79
79
|
errors=None,
|
|
80
80
|
logger=__IAM_LOGGER)
|
|
@@ -137,7 +137,7 @@ def service_setup_server() -> Response:
|
|
|
137
137
|
Entry point to setup a *IAM* server.
|
|
138
138
|
|
|
139
139
|
These are the expected parameters in the request's body, in a JSON or as form data:
|
|
140
|
-
- *iam_server*: identifies the supported *IAM* server
|
|
140
|
+
- *iam_server*: identifies the supported *IAM* server
|
|
141
141
|
- *admin_id*: identifies the realm administrator
|
|
142
142
|
- *admin_secret*: password for the realm administrator
|
|
143
143
|
- *client_id*: the client's identification with the *IAM* server
|
|
@@ -181,7 +181,7 @@ def service_setup_server() -> Response:
|
|
|
181
181
|
return result
|
|
182
182
|
|
|
183
183
|
|
|
184
|
-
# @flask_app.route(rule=<login_endpoint>,
|
|
184
|
+
# @flask_app.route(rule=<login_endpoint>,
|
|
185
185
|
# methods=["GET"])
|
|
186
186
|
def service_login() -> Response:
|
|
187
187
|
"""
|
|
@@ -240,7 +240,7 @@ def service_login() -> Response:
|
|
|
240
240
|
return result
|
|
241
241
|
|
|
242
242
|
|
|
243
|
-
# @flask_app.route(rule=<logout_endpoint>,
|
|
243
|
+
# @flask_app.route(rule=<logout_endpoint>,
|
|
244
244
|
# methods=["POST"])
|
|
245
245
|
@jwt_required
|
|
246
246
|
def service_logout() -> Response:
|
|
@@ -292,7 +292,7 @@ def service_logout() -> Response:
|
|
|
292
292
|
return result
|
|
293
293
|
|
|
294
294
|
|
|
295
|
-
# @flask_app.route(rule=<callback_endpoint>,
|
|
295
|
+
# @flask_app.route(rule=<callback_endpoint>,
|
|
296
296
|
# methods=["GET", "POST"])
|
|
297
297
|
def service_callback() -> Response:
|
|
298
298
|
"""
|
|
@@ -352,7 +352,7 @@ def service_callback() -> Response:
|
|
|
352
352
|
return result
|
|
353
353
|
|
|
354
354
|
|
|
355
|
-
# @flask_app.route(rule=<callback_endpoint>,
|
|
355
|
+
# @flask_app.route(rule=<callback_endpoint>,
|
|
356
356
|
# methods=["POST"])
|
|
357
357
|
def service_exchange() -> Response:
|
|
358
358
|
"""
|
|
@@ -490,7 +490,7 @@ def service_callback_exchange() -> Response:
|
|
|
490
490
|
return result
|
|
491
491
|
|
|
492
492
|
|
|
493
|
-
# @flask_app.route(rule=<token_endpoint>,
|
|
493
|
+
# @flask_app.route(rule=<token_endpoint>,
|
|
494
494
|
# methods=["GET"])
|
|
495
495
|
def service_get_token() -> Response:
|
|
496
496
|
"""
|
|
@@ -544,7 +544,7 @@ def service_get_token() -> Response:
|
|
|
544
544
|
return result
|
|
545
545
|
|
|
546
546
|
|
|
547
|
-
# @flask_app.route(rule=<token_endpoint>,
|
|
547
|
+
# @flask_app.route(rule=<token_endpoint>,
|
|
548
548
|
# methods=["GET"])
|
|
549
549
|
@jwt_required
|
|
550
550
|
def service_userinfo() -> Response:
|
pypomes_iam/provider_pomes.py
CHANGED
|
@@ -14,6 +14,11 @@ from pypomes_core import (
|
|
|
14
14
|
from threading import Lock
|
|
15
15
|
from typing import Any, Final
|
|
16
16
|
|
|
17
|
+
_members: dict[str, str] = {key.upper(): key.lower() for key in
|
|
18
|
+
env_get_strs(key=f"{APP_PREFIX}_AUTH_PROVIDERS")}
|
|
19
|
+
IamProvider: type[StrEnum] = StrEnum("IamProvider", _members)
|
|
20
|
+
del _members
|
|
21
|
+
|
|
17
22
|
|
|
18
23
|
class ProviderParam(StrEnum):
|
|
19
24
|
"""
|
|
@@ -36,37 +41,36 @@ class ProviderParam(StrEnum):
|
|
|
36
41
|
__JWT_LOGGER: Logger | None = None
|
|
37
42
|
|
|
38
43
|
|
|
39
|
-
def __get_provider_data() -> dict[
|
|
44
|
+
def __get_provider_data() -> dict[IamProvider, dict[ProviderParam, Any]]:
|
|
40
45
|
"""
|
|
41
|
-
Obtain the configuration data for select *
|
|
46
|
+
Obtain the configuration data for select *IAM* providers.
|
|
42
47
|
|
|
43
|
-
The configuration parameters for the
|
|
48
|
+
The configuration parameters for the *IAM* providers are specified with environment variables,
|
|
44
49
|
or dynamically with *provider_setup_server()*. Specifying configuration parameters with
|
|
45
50
|
environment variables can be done by following these steps:
|
|
46
51
|
|
|
47
52
|
1. Specify *<APP_PREFIX>_AUTH_PROVIDERS* with a list of names (typically, in lower-case), and the data set
|
|
48
|
-
below for each providers, where *<
|
|
49
|
-
- *<APP_PREFIX>_<
|
|
50
|
-
- *<APP_PREFIX>_<
|
|
51
|
-
- *<APP_PREFIX>_<
|
|
52
|
-
- *<APP_PREFIX>_<
|
|
53
|
-
- *<APP_PREFIX>_<
|
|
54
|
-
- *<APP_PREFIX>_<
|
|
53
|
+
below for each providers, where *<IAM>* stands for the provider's name in upper-case:
|
|
54
|
+
- *<APP_PREFIX>_<IAM>_BODY_DATA* (optional)
|
|
55
|
+
- *<APP_PREFIX>_<IAM>_CUSTOM_AUTH* (optional)
|
|
56
|
+
- *<APP_PREFIX>_<IAM>_HEADER_DATA* (optional)
|
|
57
|
+
- *<APP_PREFIX>_<IAM>_USER_ID* (required)
|
|
58
|
+
- *<APP_PREFIX>_<IAM>_USER_SECRET* (required)
|
|
59
|
+
- *<APP_PREFIX>_<IAM>_URL_TOKEN* (required)
|
|
55
60
|
|
|
56
61
|
2. The special environment variable *<APP_PREFIX>_PROVIDER_ENDPOINT_TOKEN* identifies the endpoint
|
|
57
62
|
from which to obtain JWT tokens. It is not part of the *JWT* providers' setup, but is meant to be
|
|
58
63
|
used by function *provider_setup_endpoint()*, wherein the value in that variable would represent
|
|
59
64
|
the default value for its parameter.
|
|
60
65
|
|
|
61
|
-
:return: the configuration data for the select *
|
|
66
|
+
:return: the configuration data for the select *IAM* providers.
|
|
62
67
|
"""
|
|
63
68
|
# initialize the return variable
|
|
64
69
|
result: dict[str, dict[ProviderParam, Any]] = {}
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
result[server] = {
|
|
71
|
+
for provider in IamProvider:
|
|
72
|
+
prefix = provider.name
|
|
73
|
+
result[provider] = {
|
|
70
74
|
ProviderParam.USER_ID: env_get_str(key=f"{APP_PREFIX}_{prefix}_USER_ID"),
|
|
71
75
|
ProviderParam.USER_SECRET: env_get_str(key=f"{APP_PREFIX}_{prefix}_USER_SECRET"),
|
|
72
76
|
ProviderParam.BODY_DATA: env_get_obj(key=f"{APP_PREFIX}_{prefix}_BODY_DATA"),
|
|
@@ -98,7 +102,7 @@ def __get_provider_data() -> dict[str, dict[ProviderParam, Any]]:
|
|
|
98
102
|
# "refresh-expiration": <timestamp>
|
|
99
103
|
# }
|
|
100
104
|
# }
|
|
101
|
-
_provider_registry: Final[dict[
|
|
105
|
+
_provider_registry: Final[dict[IamProvider, dict[str, Any]]] = __get_provider_data()
|
|
102
106
|
|
|
103
107
|
# the lock protecting the data in '_provider_registry'
|
|
104
108
|
# (because it is 'Final' and set at declaration time, it can be accessed through simple imports)
|
|
@@ -106,15 +110,15 @@ _provider_lock: Final[Lock] = Lock()
|
|
|
106
110
|
|
|
107
111
|
|
|
108
112
|
@func_capture_params
|
|
109
|
-
def
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
def iam_setup_provider(iam_provider: IamProvider,
|
|
114
|
+
user_id: str = None,
|
|
115
|
+
user_secret: str = None,
|
|
116
|
+
custom_auth: tuple[str, str] = None,
|
|
117
|
+
header_data: dict[str, str] = None,
|
|
118
|
+
body_data: dict[str, str] = None,
|
|
119
|
+
url_token: str = None) -> None:
|
|
116
120
|
"""
|
|
117
|
-
Setup the *
|
|
121
|
+
Setup the *IAM* provider *iam_provider*.
|
|
118
122
|
|
|
119
123
|
For the parameters not effectively passed, an attempt is made to obtain a value from the corresponding
|
|
120
124
|
environment variable.
|
|
@@ -128,7 +132,7 @@ def provider_setup_server(provider_id: str,
|
|
|
128
132
|
key-value pairs (such as *['grant_type', 'client_credentials']*), to be added to the request body,
|
|
129
133
|
may be specified in *body_data*.
|
|
130
134
|
|
|
131
|
-
:param
|
|
135
|
+
:param iam_provider: the provider's identification
|
|
132
136
|
:param user_id: the basic authorization user
|
|
133
137
|
:param user_secret: the basic authorization password
|
|
134
138
|
:param custom_auth: optional key names for sending the credentials as key-value pairs in the body of the request
|
|
@@ -142,7 +146,7 @@ def provider_setup_server(provider_id: str,
|
|
|
142
146
|
defaulted_params: list[str] = func_defaulted_params.get()
|
|
143
147
|
|
|
144
148
|
# read from the environment variables
|
|
145
|
-
prefix: str =
|
|
149
|
+
prefix: str = iam_provider.name
|
|
146
150
|
if "user_id" in defaulted_params:
|
|
147
151
|
user_id = env_get_str(key=f"{APP_PREFIX}_{prefix}_USER_ID")
|
|
148
152
|
if "user_secret" in defaulted_params:
|
|
@@ -157,7 +161,7 @@ def provider_setup_server(provider_id: str,
|
|
|
157
161
|
url_token = env_get_str(key=f"{APP_PREFIX}_{prefix}_URL_TOKEN")
|
|
158
162
|
|
|
159
163
|
with _provider_lock:
|
|
160
|
-
_provider_registry[
|
|
164
|
+
_provider_registry[iam_provider] = {
|
|
161
165
|
ProviderParam.BODY_DATA: body_data,
|
|
162
166
|
ProviderParam.CUSTOM_AUTH: custom_auth,
|
|
163
167
|
ProviderParam.HEADER_DATA: header_data,
|
|
@@ -209,7 +213,7 @@ def provider_setup_logger(logger: Logger) -> None:
|
|
|
209
213
|
__JWT_LOGGER = logger
|
|
210
214
|
|
|
211
215
|
|
|
212
|
-
# @flask_app.route(rule=<token_endpoint>,
|
|
216
|
+
# @flask_app.route(rule=<token_endpoint>,
|
|
213
217
|
# methods=["GET"])
|
|
214
218
|
def service_get_token() -> Response:
|
|
215
219
|
"""
|
|
@@ -233,17 +237,18 @@ def service_get_token() -> Response:
|
|
|
233
237
|
ensure_ascii=False)}")
|
|
234
238
|
|
|
235
239
|
# obtain the provider JWT
|
|
236
|
-
provider_id: str = args.get("
|
|
240
|
+
provider_id: str = args.get("iam-provider")
|
|
241
|
+
iam_provider: IamProvider = IamProvider(provider_id) if provider_id in IamProvider else None
|
|
237
242
|
|
|
238
243
|
# retrieve the token
|
|
239
244
|
token: str | None = None
|
|
240
245
|
errors: list[str] = []
|
|
241
|
-
if
|
|
242
|
-
token: str = provider_get_token(
|
|
246
|
+
if iam_provider:
|
|
247
|
+
token: str = provider_get_token(iam_provider=iam_provider,
|
|
243
248
|
errors=errors,
|
|
244
249
|
logger=__JWT_LOGGER)
|
|
245
250
|
else:
|
|
246
|
-
msg: str = "
|
|
251
|
+
msg: str = "IAM provider unknown or not informed"
|
|
247
252
|
errors.append(msg)
|
|
248
253
|
if __JWT_LOGGER:
|
|
249
254
|
__JWT_LOGGER.error(msg=msg)
|
|
@@ -261,13 +266,13 @@ def service_get_token() -> Response:
|
|
|
261
266
|
return result
|
|
262
267
|
|
|
263
268
|
|
|
264
|
-
def provider_get_token(
|
|
269
|
+
def provider_get_token(iam_provider: IamProvider,
|
|
265
270
|
errors: list[str] = None,
|
|
266
271
|
logger: Logger = None) -> str | None:
|
|
267
272
|
"""
|
|
268
273
|
Obtain an JWT token from the external provider *provider_id*.
|
|
269
274
|
|
|
270
|
-
:param
|
|
275
|
+
:param iam_provider: the provider's identification
|
|
271
276
|
:param errors: incidental error messages
|
|
272
277
|
:param logger: optional logger
|
|
273
278
|
:return: the JWT token, or *None* if error
|
|
@@ -278,7 +283,7 @@ def provider_get_token(provider_id: str,
|
|
|
278
283
|
result: str | None = None
|
|
279
284
|
|
|
280
285
|
with _provider_lock:
|
|
281
|
-
provider: dict[str, Any] = _provider_registry.get(
|
|
286
|
+
provider: dict[str, Any] = _provider_registry.get(iam_provider)
|
|
282
287
|
if provider:
|
|
283
288
|
now: int = int(datetime.now(tz=TZ_LOCAL).timestamp())
|
|
284
289
|
if now < provider.get(ProviderParam.ACCESS_EXPIRATION):
|
|
@@ -334,7 +339,7 @@ def provider_get_token(provider_id: str,
|
|
|
334
339
|
if refresh_exp else sys.maxsize
|
|
335
340
|
|
|
336
341
|
elif logger or isinstance(errors, list):
|
|
337
|
-
msg: str = f"Unknown provider '{
|
|
342
|
+
msg: str = f"Unknown provider '{iam_provider}'"
|
|
338
343
|
if logger:
|
|
339
344
|
logger.error(msg=msg)
|
|
340
345
|
if isinstance(errors, list):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pypomes_iam
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.9
|
|
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,11 @@
|
|
|
1
|
+
pypomes_iam/__init__.py,sha256=TU9WVKe9CdfEH2bFnLv249Hzo9xIq6NT8SgIUzWYlZE,1685
|
|
2
|
+
pypomes_iam/iam_actions.py,sha256=NY3gsZK72JQAUAwt8LsaSYhrbXdxyIcbzaG1U-VNF70,51234
|
|
3
|
+
pypomes_iam/iam_common.py,sha256=P2IzDQhfrf40VZBkC4p4pOUbR0IW7kq5_xmcAzPvW5s,17546
|
|
4
|
+
pypomes_iam/iam_pomes.py,sha256=2yLTOY_A8bkM7QsOynJOdmVoMu8ZSwFaO7RmxHVDDsU,8931
|
|
5
|
+
pypomes_iam/iam_services.py,sha256=4k2MEKQG5xwHuZylVLFGyohXRlraB4BXBOVPWxig2tg,26689
|
|
6
|
+
pypomes_iam/provider_pomes.py,sha256=uhH8tqdA6AVC8TiPfFdH5gkrrEw_cpkLerRFICdks58,17954
|
|
7
|
+
pypomes_iam/token_pomes.py,sha256=KiTlBNj3HURbZS_Rmti2RC6hny8VFPpbXeIO--HZ-fI,7703
|
|
8
|
+
pypomes_iam-0.8.9.dist-info/METADATA,sha256=y586FcTfUOqMNv9YRjmm_ssEbPVmNxxuQMrTrdDA5Kk,661
|
|
9
|
+
pypomes_iam-0.8.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
10
|
+
pypomes_iam-0.8.9.dist-info/licenses/LICENSE,sha256=YvUELgV8qvXlaYsy9hXG5EW3Bmsrkw-OJmmILZnonAc,1086
|
|
11
|
+
pypomes_iam-0.8.9.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
pypomes_iam/__init__.py,sha256=kkHvF3P79h21dNBmJ566Mp-L27oejhBcJa2VquyVsdg,1619
|
|
2
|
-
pypomes_iam/iam_actions.py,sha256=ORuHoiuMPnrMabvnCUcMeqHI4xfqbTErED1LydOPBCg,51191
|
|
3
|
-
pypomes_iam/iam_common.py,sha256=lJAx0J7xjAyzaMI9WXUXRq2qO7bUGIUP85h1hNE2-RE,17569
|
|
4
|
-
pypomes_iam/iam_pomes.py,sha256=VwqK3FoGj76SHKLARuBmIhziYnd_hoMWoUteMGRjuSc,8963
|
|
5
|
-
pypomes_iam/iam_services.py,sha256=_oAAk3y6iw_2gxDkbcNJDmj6Mk8HByhqX8fUT6Qg9kU,26865
|
|
6
|
-
pypomes_iam/provider_pomes.py,sha256=e2AFGQgEajDOvr47LJYAqJ9Eaf0G0MrBAKKC4JK2Jp0,17705
|
|
7
|
-
pypomes_iam/token_pomes.py,sha256=KiTlBNj3HURbZS_Rmti2RC6hny8VFPpbXeIO--HZ-fI,7703
|
|
8
|
-
pypomes_iam-0.8.5.dist-info/METADATA,sha256=z0_4gG_jLZVliMWrQzcRw9AJD58V703MZjT4ZIfKXEo,661
|
|
9
|
-
pypomes_iam-0.8.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
10
|
-
pypomes_iam-0.8.5.dist-info/licenses/LICENSE,sha256=YvUELgV8qvXlaYsy9hXG5EW3Bmsrkw-OJmmILZnonAc,1086
|
|
11
|
-
pypomes_iam-0.8.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|