pypomes-iam 0.2.1__tar.gz → 0.2.2__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-iam might be problematic. Click here for more details.
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/PKG-INFO +1 -1
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/pyproject.toml +1 -1
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/src/pypomes_iam/common_pomes.py +71 -71
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/src/pypomes_iam/iam_pomes.py +18 -18
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/src/pypomes_iam/jusbr_pomes.py +16 -0
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/src/pypomes_iam/keycloak_pomes.py +16 -0
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/.gitignore +0 -0
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/LICENSE +0 -0
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/README.md +0 -0
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/src/pypomes_iam/__init__.py +0 -0
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/src/pypomes_iam/provider_pomes.py +0 -0
- {pypomes_iam-0.2.1 → pypomes_iam-0.2.2}/src/pypomes_iam/token_pomes.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pypomes_iam
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
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
|
|
@@ -8,6 +8,7 @@ from datetime import datetime
|
|
|
8
8
|
from flask import Request
|
|
9
9
|
from logging import Logger
|
|
10
10
|
from pypomes_core import TZ_LOCAL, exc_format
|
|
11
|
+
from pypomes_crypto import crypto_jwk_convert
|
|
11
12
|
from typing import Any
|
|
12
13
|
|
|
13
14
|
# registry structure:
|
|
@@ -36,75 +37,6 @@ from typing import Any
|
|
|
36
37
|
# }
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
def _service_callback(registry: dict[str, Any],
|
|
40
|
-
args: dict[str, Any],
|
|
41
|
-
errors: list[str],
|
|
42
|
-
logger: Logger | None) -> tuple[str, str]:
|
|
43
|
-
"""
|
|
44
|
-
Entry point for the callback from JusBR on authentication operation.
|
|
45
|
-
|
|
46
|
-
:param registry: the registry holding the authentication data
|
|
47
|
-
:param args: the arguments passed when requesting the service
|
|
48
|
-
:param errors: incidental errors
|
|
49
|
-
:param logger: optional logger
|
|
50
|
-
"""
|
|
51
|
-
from .token_pomes import token_validate
|
|
52
|
-
|
|
53
|
-
# initialize the return variable
|
|
54
|
-
result: tuple[str, str] | None = None
|
|
55
|
-
|
|
56
|
-
# retrieve the users authentication data
|
|
57
|
-
cache: Cache = registry["safe-cache"]
|
|
58
|
-
users: dict[str, dict[str, Any]] = cache.get("users")
|
|
59
|
-
|
|
60
|
-
# validate the OAuth2 state
|
|
61
|
-
oauth_state: str = args.get("state")
|
|
62
|
-
user_data: dict[str, Any] | None = None
|
|
63
|
-
if oauth_state:
|
|
64
|
-
for user, data in users.items():
|
|
65
|
-
if user == oauth_state:
|
|
66
|
-
user_data = data
|
|
67
|
-
break
|
|
68
|
-
|
|
69
|
-
# exchange 'code' for the token
|
|
70
|
-
if user_data:
|
|
71
|
-
users.pop(oauth_state)
|
|
72
|
-
code: str = args.get("code")
|
|
73
|
-
body_data: dict[str, Any] = {
|
|
74
|
-
"grant_type": "authorization_code",
|
|
75
|
-
"code": code,
|
|
76
|
-
"redirect_uri": registry.get("callback-url"),
|
|
77
|
-
}
|
|
78
|
-
token = _post_for_token(registry=registry,
|
|
79
|
-
user_data=user_data,
|
|
80
|
-
body_data=body_data,
|
|
81
|
-
errors=errors,
|
|
82
|
-
logger=logger)
|
|
83
|
-
# retrieve the token's claims
|
|
84
|
-
if not errors:
|
|
85
|
-
public_key: bytes = _get_public_key(registry=registry,
|
|
86
|
-
logger=logger)
|
|
87
|
-
token_claims: dict[str, dict[str, Any]] = token_validate(token=token,
|
|
88
|
-
issuer=registry["base-url"],
|
|
89
|
-
public_key=public_key,
|
|
90
|
-
errors=errors,
|
|
91
|
-
logger=logger)
|
|
92
|
-
if not errors:
|
|
93
|
-
token_user: str = token_claims["payload"].get("preferred_username")
|
|
94
|
-
if token_user == oauth_state:
|
|
95
|
-
users[token_user] = user_data
|
|
96
|
-
result = (token_user, token)
|
|
97
|
-
else:
|
|
98
|
-
errors.append(f"Token was issued to user '{token_user}'")
|
|
99
|
-
else:
|
|
100
|
-
msg: str = "Unknown OAuth2 code received"
|
|
101
|
-
if _get_login_timeout(registry=registry):
|
|
102
|
-
msg += " - possible operation timeout"
|
|
103
|
-
errors.append(msg)
|
|
104
|
-
|
|
105
|
-
return result
|
|
106
|
-
|
|
107
|
-
|
|
108
40
|
def _service_login(registry: dict[str, Any],
|
|
109
41
|
args: dict[str, Any],
|
|
110
42
|
logger: Logger | None) -> str:
|
|
@@ -165,6 +97,76 @@ def _service_logout(registry: dict[str, Any],
|
|
|
165
97
|
logger.debug(msg=f"User '{user_id}' removed from the registry")
|
|
166
98
|
|
|
167
99
|
|
|
100
|
+
def _service_callback(registry: dict[str, Any],
|
|
101
|
+
args: dict[str, Any],
|
|
102
|
+
errors: list[str],
|
|
103
|
+
logger: Logger | None) -> tuple[str, str]:
|
|
104
|
+
"""
|
|
105
|
+
Entry point for the callback from JusBR on authentication operation.
|
|
106
|
+
|
|
107
|
+
:param registry: the registry holding the authentication data
|
|
108
|
+
:param args: the arguments passed when requesting the service
|
|
109
|
+
:param errors: incidental errors
|
|
110
|
+
:param logger: optional logger
|
|
111
|
+
"""
|
|
112
|
+
from .token_pomes import token_validate
|
|
113
|
+
|
|
114
|
+
# initialize the return variable
|
|
115
|
+
result: tuple[str, str] | None = None
|
|
116
|
+
|
|
117
|
+
# retrieve the users authentication data
|
|
118
|
+
cache: Cache = registry["safe-cache"]
|
|
119
|
+
users: dict[str, dict[str, Any]] = cache.get("users")
|
|
120
|
+
|
|
121
|
+
# validate the OAuth2 state
|
|
122
|
+
oauth_state: str = args.get("state")
|
|
123
|
+
user_data: dict[str, Any] | None = None
|
|
124
|
+
if oauth_state:
|
|
125
|
+
for user, data in users.items():
|
|
126
|
+
if user == oauth_state:
|
|
127
|
+
user_data = data
|
|
128
|
+
break
|
|
129
|
+
|
|
130
|
+
# exchange 'code' for the token
|
|
131
|
+
if user_data:
|
|
132
|
+
expiration: int = user_data["login-expiration"] or sys.maxsize
|
|
133
|
+
if int(datetime.now(tz=TZ_LOCAL).timestamp()) > expiration:
|
|
134
|
+
errors.append("Operation timeout")
|
|
135
|
+
else:
|
|
136
|
+
users.pop(oauth_state)
|
|
137
|
+
code: str = args.get("code")
|
|
138
|
+
body_data: dict[str, Any] = {
|
|
139
|
+
"grant_type": "authorization_code",
|
|
140
|
+
"code": code,
|
|
141
|
+
"redirect_uri": registry.get("callback-url"),
|
|
142
|
+
}
|
|
143
|
+
token = _post_for_token(registry=registry,
|
|
144
|
+
user_data=user_data,
|
|
145
|
+
body_data=body_data,
|
|
146
|
+
errors=errors,
|
|
147
|
+
logger=logger)
|
|
148
|
+
# retrieve the token's claims
|
|
149
|
+
if not errors:
|
|
150
|
+
public_key: bytes = _get_public_key(registry=registry,
|
|
151
|
+
logger=logger)
|
|
152
|
+
token_claims: dict[str, dict[str, Any]] = token_validate(token=token,
|
|
153
|
+
issuer=registry["base-url"],
|
|
154
|
+
public_key=public_key,
|
|
155
|
+
errors=errors,
|
|
156
|
+
logger=logger)
|
|
157
|
+
if not errors:
|
|
158
|
+
token_user: str = token_claims["payload"].get("preferred_username")
|
|
159
|
+
if token_user == oauth_state:
|
|
160
|
+
users[token_user] = user_data
|
|
161
|
+
result = (token_user, token)
|
|
162
|
+
else:
|
|
163
|
+
errors.append(f"Token was issued to user '{token_user}'")
|
|
164
|
+
else:
|
|
165
|
+
errors.append("Unknown state received")
|
|
166
|
+
|
|
167
|
+
return result
|
|
168
|
+
|
|
169
|
+
|
|
168
170
|
def _service_token(registry: dict[str, Any],
|
|
169
171
|
args: dict[str, Any],
|
|
170
172
|
errors: list[str] = None,
|
|
@@ -225,8 +227,6 @@ def _get_public_key(registry: dict[str, Any],
|
|
|
225
227
|
:param registry: the registry holding the authentication data
|
|
226
228
|
:return: the public key, in *DER* format
|
|
227
229
|
"""
|
|
228
|
-
from pypomes_crypto import crypto_jwk_convert
|
|
229
|
-
|
|
230
230
|
# initialize the return variable
|
|
231
231
|
result: bytes | None = None
|
|
232
232
|
|
|
@@ -6,8 +6,8 @@ from .common_pomes import (
|
|
|
6
6
|
_service_login, _service_logout,
|
|
7
7
|
_service_callback, _service_token, _log_init
|
|
8
8
|
)
|
|
9
|
-
from .jusbr_pomes import
|
|
10
|
-
from .keycloak_pomes import
|
|
9
|
+
from .jusbr_pomes import _jusbr_get_logger, _jusbr_get_registry
|
|
10
|
+
from .keycloak_pomes import _keycloak_get_logger, _keycloak_get_registry
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
# @flask_app.route(rule=<login_endpoint>, # JUSBR_LOGIN_ENDPOINT: /iam/jusbr:login
|
|
@@ -25,11 +25,11 @@ def service_login() -> Response:
|
|
|
25
25
|
logger: Logger
|
|
26
26
|
registry: dict[str, Any]
|
|
27
27
|
if request.endpoint == "jusbr-login":
|
|
28
|
-
logger =
|
|
29
|
-
registry =
|
|
28
|
+
logger = _jusbr_get_logger()
|
|
29
|
+
registry = _jusbr_get_registry()
|
|
30
30
|
else:
|
|
31
|
-
logger =
|
|
32
|
-
registry =
|
|
31
|
+
logger = _keycloak_get_logger()
|
|
32
|
+
registry = _keycloak_get_registry()
|
|
33
33
|
|
|
34
34
|
# log the request
|
|
35
35
|
if logger:
|
|
@@ -64,11 +64,11 @@ def service_logout() -> Response:
|
|
|
64
64
|
logger: Logger
|
|
65
65
|
registry: dict[str, Any]
|
|
66
66
|
if request.endpoint == "jusbr-logout":
|
|
67
|
-
logger =
|
|
68
|
-
registry =
|
|
67
|
+
logger = _jusbr_get_logger()
|
|
68
|
+
registry = _jusbr_get_registry()
|
|
69
69
|
else:
|
|
70
|
-
logger =
|
|
71
|
-
registry =
|
|
70
|
+
logger = _keycloak_get_logger()
|
|
71
|
+
registry = _keycloak_get_registry()
|
|
72
72
|
|
|
73
73
|
# log the request
|
|
74
74
|
if logger:
|
|
@@ -101,11 +101,11 @@ def service_callback() -> Response:
|
|
|
101
101
|
logger: Logger
|
|
102
102
|
registry: dict[str, Any]
|
|
103
103
|
if request.endpoint == "jusbr-callback":
|
|
104
|
-
logger =
|
|
105
|
-
registry =
|
|
104
|
+
logger = _jusbr_get_logger()
|
|
105
|
+
registry = _jusbr_get_registry()
|
|
106
106
|
else:
|
|
107
|
-
logger =
|
|
108
|
-
registry =
|
|
107
|
+
logger = _keycloak_get_logger()
|
|
108
|
+
registry = _keycloak_get_registry()
|
|
109
109
|
|
|
110
110
|
# log the request
|
|
111
111
|
if logger:
|
|
@@ -146,11 +146,11 @@ def service_token() -> Response:
|
|
|
146
146
|
logger: Logger
|
|
147
147
|
registry: dict[str, Any]
|
|
148
148
|
if request.endpoint == "jusbr-token":
|
|
149
|
-
logger =
|
|
150
|
-
registry =
|
|
149
|
+
logger = _jusbr_get_logger()
|
|
150
|
+
registry = _jusbr_get_registry()
|
|
151
151
|
else:
|
|
152
|
-
logger =
|
|
153
|
-
registry =
|
|
152
|
+
logger = _keycloak_get_logger()
|
|
153
|
+
registry = _keycloak_get_registry()
|
|
154
154
|
|
|
155
155
|
# log the request
|
|
156
156
|
if logger:
|
|
@@ -147,3 +147,19 @@ def jusbr_get_token(user_id: str,
|
|
|
147
147
|
args=args,
|
|
148
148
|
errors=errors,
|
|
149
149
|
logger=logger)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _jusbr_get_logger() -> Logger:
|
|
153
|
+
"""
|
|
154
|
+
Retrieve the logger for JusBR operations.
|
|
155
|
+
:return: the Keycloak logger
|
|
156
|
+
"""
|
|
157
|
+
return _jusbr_logger
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _jusbr_get_registry() -> dict[str, Any]:
|
|
161
|
+
"""
|
|
162
|
+
Retrieve the registry holding user authentication data related to JusBR operations.
|
|
163
|
+
:return: the Keycloak registry
|
|
164
|
+
"""
|
|
165
|
+
return _jusbr_registry
|
|
@@ -150,3 +150,19 @@ def keycloak_get_token(user_id: str,
|
|
|
150
150
|
args=args,
|
|
151
151
|
errors=errors,
|
|
152
152
|
logger=logger)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _keycloak_get_logger() -> Logger:
|
|
156
|
+
"""
|
|
157
|
+
Retrieve the logger for Keycloak operations.
|
|
158
|
+
:return: the Keycloak logger
|
|
159
|
+
"""
|
|
160
|
+
return _keycloak_logger
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _keycloak_get_registry() -> dict[str, Any]:
|
|
164
|
+
"""
|
|
165
|
+
Retrieve the registry holding user authentication data related to Keycloak operations.
|
|
166
|
+
:return: the Keycloak registry
|
|
167
|
+
"""
|
|
168
|
+
return _keycloak_registry
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|