oidcauthlib 3.0.6__tar.gz → 3.0.8__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.
- oidcauthlib-3.0.8/MANIFEST.in +1 -0
- {oidcauthlib-3.0.6/oidcauthlib.egg-info → oidcauthlib-3.0.8}/PKG-INFO +5 -14
- oidcauthlib-3.0.8/VERSION +1 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/auth_helper.py +2 -6
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/auth_manager.py +35 -53
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/cache/oauth_memory_cache.py +1 -2
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/cache/oauth_mongo_cache.py +13 -35
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/config/auth_config.py +1 -2
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/config/auth_config_reader.py +24 -72
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/dcr/dcr_client.py +3 -6
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/dcr/dcr_manager.py +9 -17
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/dcr/dcr_registration.py +3 -9
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/fastapi_auth_manager.py +92 -34
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/middleware/request_scope_middleware.py +4 -11
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/middleware/token_reader_middleware.py +7 -21
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/models/auth.py +2 -6
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/models/cache_item.py +1 -3
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/models/client_key_set.py +2 -6
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/models/token.py +6 -26
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/repository/base_repository.py +2 -6
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/repository/memory/memory_repository.py +2 -8
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/repository/mongo/mongo_repository.py +14 -42
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/repository/repository_factory.py +2 -6
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/routers/auth_router.py +9 -29
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/token_reader.py +8 -26
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/well_known_configuration/auth_server_metadata_discovery.py +1 -2
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/well_known_configuration/well_known_configuration_cache.py +32 -92
- oidcauthlib-3.0.8/oidcauthlib/auth/well_known_configuration/well_known_configuration_cache_result.py +9 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/well_known_configuration/well_known_configuration_manager.py +2 -6
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/container/oidc_authlib_container_factory.py +5 -15
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/storage/mongo_gridfs_db.py +26 -77
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/storage/mongo_storage_factory.py +5 -13
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/storage/storage_factory_creator.py +2 -5
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/environment/oidc_environment_variables.py +8 -24
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/logger/logging_response.py +2 -6
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/mongo_url_utils.py +1 -3
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8/oidcauthlib.egg-info}/PKG-INFO +5 -14
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib.egg-info/SOURCES.txt +2 -50
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib.egg-info/top_level.txt +0 -1
- oidcauthlib-3.0.8/pyproject.toml +108 -0
- oidcauthlib-3.0.8/setup.cfg +4 -0
- oidcauthlib-3.0.6/MANIFEST.in +0 -6
- oidcauthlib-3.0.6/Makefile +0 -85
- oidcauthlib-3.0.6/VERSION +0 -1
- oidcauthlib-3.0.6/oidcauthlib/auth/well_known_configuration/well_known_configuration_cache_result.py +0 -15
- oidcauthlib-3.0.6/oidcauthlib.egg-info/not-zip-safe +0 -1
- oidcauthlib-3.0.6/setup.cfg +0 -29
- oidcauthlib-3.0.6/setup.py +0 -82
- oidcauthlib-3.0.6/tests/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/cache/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/cache/test_oauth_memory_cache.py +0 -26
- oidcauthlib-3.0.6/tests/auth/config/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/config/test_auth_config.py +0 -72
- oidcauthlib-3.0.6/tests/auth/config/test_auth_config_reader.py +0 -91
- oidcauthlib-3.0.6/tests/auth/config/test_auth_config_reader_register.py +0 -200
- oidcauthlib-3.0.6/tests/auth/config/test_auth_config_reader_thread_safety.py +0 -127
- oidcauthlib-3.0.6/tests/auth/conftest.py +0 -14
- oidcauthlib-3.0.6/tests/auth/dcr/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/dcr/test_dcr_client.py +0 -129
- oidcauthlib-3.0.6/tests/auth/dcr/test_dcr_manager.py +0 -198
- oidcauthlib-3.0.6/tests/auth/middleware/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/middleware/test_request_scope_middleware.py +0 -188
- oidcauthlib-3.0.6/tests/auth/middleware/test_token_reader_middleware.py +0 -671
- oidcauthlib-3.0.6/tests/auth/models/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/models/test_auth.py +0 -43
- oidcauthlib-3.0.6/tests/auth/models/test_base_db_model.py +0 -70
- oidcauthlib-3.0.6/tests/auth/models/test_cache_item.py +0 -17
- oidcauthlib-3.0.6/tests/auth/models/test_token.py +0 -48
- oidcauthlib-3.0.6/tests/auth/repository/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/repository/memory/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/repository/memory/test_memory_repository.py +0 -156
- oidcauthlib-3.0.6/tests/auth/repository/mongo/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/repository/mongo/test_mongo_repository.py +0 -912
- oidcauthlib-3.0.6/tests/auth/repository/mongo/test_mongo_repository_real.py +0 -178
- oidcauthlib-3.0.6/tests/auth/test_auth_helper.py +0 -26
- oidcauthlib-3.0.6/tests/auth/test_auth_helper2.py +0 -33
- oidcauthlib-3.0.6/tests/auth/test_auth_manager.py +0 -523
- oidcauthlib-3.0.6/tests/auth/test_register_dynamic_provider.py +0 -357
- oidcauthlib-3.0.6/tests/auth/well_known_configuration/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/auth/well_known_configuration/test_auth_server_metadata_discovery.py +0 -184
- oidcauthlib-3.0.6/tests/auth/well_known_configuration/test_well_known_configuration_cache.py +0 -405
- oidcauthlib-3.0.6/tests/auth/well_known_configuration/test_well_known_configuration_manager.py +0 -174
- oidcauthlib-3.0.6/tests/conftest.py +0 -130
- oidcauthlib-3.0.6/tests/storage/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/storage/test_mongo_gridfs_db.py +0 -378
- oidcauthlib-3.0.6/tests/storage/test_mongo_gridfs_race_setup.py +0 -70
- oidcauthlib-3.0.6/tests/storage/test_mongo_store_factory.py +0 -516
- oidcauthlib-3.0.6/tests/storage/test_storage_factory_security.py +0 -498
- oidcauthlib-3.0.6/tests/utilities/__init__.py +0 -0
- oidcauthlib-3.0.6/tests/utilities/test_cached.py +0 -52
- oidcauthlib-3.0.6/tests/utilities/test_mongo_url_utils.py +0 -30
- oidcauthlib-3.0.6/tests/utilities/test_url_validator.py +0 -182
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/LICENSE +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/README.md +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/cache/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/cache/oauth_cache.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/config/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/dcr/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/exceptions/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/exceptions/authorization_bearer_token_expired_exception.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/exceptions/authorization_bearer_token_invalid_exception.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/exceptions/authorization_bearer_token_missing_exception.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/exceptions/authorization_needed_exception.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/middleware/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/models/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/models/base_db_model.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/repository/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/repository/memory/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/repository/mongo/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/routers/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/well_known_configuration/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/auth/well_known_configuration/auth_server_metadata.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/container/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/open_telemetry/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/open_telemetry/attribute_names.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/open_telemetry/span_names.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/py.typed +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/storage/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/storage/cache_to_collection_mapper.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/storage/memory_storage_factory.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/storage/mongo_gridfs_exception.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/storage/storage_factory.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/cached.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/environment/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/environment/abstract_environment_variables.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/logger/__init__.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/logger/log_levels.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/logger/logging_transport.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib/utilities/url_validator.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib.egg-info/dependency_links.txt +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/oidcauthlib.egg-info/requires.txt +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/tests/test_mongo_url_utils.py +0 -0
- {oidcauthlib-3.0.6 → oidcauthlib-3.0.8}/tests/test_simple.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include VERSION
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oidcauthlib
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.8
|
|
4
4
|
Summary: oidcauthlib
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Author-email: Imran Qureshi <imran.qureshi@bwell.com>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/icanbwell/oidc-auth-lib
|
|
8
8
|
Classifier: Development Status :: 4 - Beta
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
@@ -23,15 +23,6 @@ Requires-Dist: starlette>=0.49.1
|
|
|
23
23
|
Requires-Dist: py-key-value-aio[memory,mongodb,pydantic,redis]>=0.4.4
|
|
24
24
|
Requires-Dist: opentelemetry-api>=1.39.1
|
|
25
25
|
Requires-Dist: simple-container>=1.0.2
|
|
26
|
-
Dynamic: author
|
|
27
|
-
Dynamic: author-email
|
|
28
|
-
Dynamic: classifier
|
|
29
|
-
Dynamic: description
|
|
30
|
-
Dynamic: description-content-type
|
|
31
|
-
Dynamic: home-page
|
|
32
26
|
Dynamic: license-file
|
|
33
|
-
Dynamic: requires-dist
|
|
34
|
-
Dynamic: requires-python
|
|
35
|
-
Dynamic: summary
|
|
36
27
|
|
|
37
28
|
# oidcauthlib
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.0.8
|
|
@@ -21,9 +21,7 @@ class AuthHelper:
|
|
|
21
21
|
A base64url encoded string of the content.
|
|
22
22
|
"""
|
|
23
23
|
json_content = json.dumps(content)
|
|
24
|
-
encoded_content = base64.urlsafe_b64encode(json_content.encode("utf-8")).decode(
|
|
25
|
-
"utf-8"
|
|
26
|
-
)
|
|
24
|
+
encoded_content = base64.urlsafe_b64encode(json_content.encode("utf-8")).decode("utf-8")
|
|
27
25
|
return encoded_content.rstrip("=")
|
|
28
26
|
|
|
29
27
|
@staticmethod
|
|
@@ -56,9 +54,7 @@ class AuthHelper:
|
|
|
56
54
|
logger.error(f"Failed to decode state (JSON error): {e}")
|
|
57
55
|
raise ValueError("Invalid JSON in decoded state") from e
|
|
58
56
|
if not isinstance(result, dict):
|
|
59
|
-
logger.error(
|
|
60
|
-
"Failed to decode state: Decoded state is not a dictionary"
|
|
61
|
-
)
|
|
57
|
+
logger.error("Failed to decode state: Decoded state is not a dictionary")
|
|
62
58
|
raise ValueError("Decoded state is not a dictionary")
|
|
63
59
|
return result
|
|
64
60
|
except Exception:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import logging
|
|
2
3
|
import os
|
|
3
4
|
import time
|
|
@@ -37,6 +38,7 @@ from oidcauthlib.utilities.url_validator import validate_url
|
|
|
37
38
|
|
|
38
39
|
logger = logging.getLogger(__name__)
|
|
39
40
|
logger.setLevel(SRC_LOG_LEVELS["AUTH"])
|
|
41
|
+
OAUTH_STATE_CACHE_TTL_SECONDS: int = int(os.getenv("OAUTH_STATE_CACHE_TTL_SECONDS", "300"))
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
class AuthManager:
|
|
@@ -70,17 +72,13 @@ class AuthManager:
|
|
|
70
72
|
if self.environment_variables is None:
|
|
71
73
|
raise ValueError("environment_variables must not be None")
|
|
72
74
|
if not isinstance(self.environment_variables, AbstractEnvironmentVariables):
|
|
73
|
-
raise TypeError(
|
|
74
|
-
"environment_variables must be an instance of EnvironmentVariables"
|
|
75
|
-
)
|
|
75
|
+
raise TypeError("environment_variables must be an instance of EnvironmentVariables")
|
|
76
76
|
|
|
77
77
|
self.auth_config_reader: AuthConfigReader = auth_config_reader
|
|
78
78
|
if self.auth_config_reader is None:
|
|
79
79
|
raise ValueError("auth_config_reader must not be None")
|
|
80
80
|
if not isinstance(self.auth_config_reader, AuthConfigReader):
|
|
81
|
-
raise TypeError(
|
|
82
|
-
"auth_config_reader must be an instance of AuthConfigReader"
|
|
83
|
-
)
|
|
81
|
+
raise TypeError("auth_config_reader must be an instance of AuthConfigReader")
|
|
84
82
|
|
|
85
83
|
self.token_reader: TokenReader = token_reader
|
|
86
84
|
if self.token_reader is None:
|
|
@@ -88,17 +86,11 @@ class AuthManager:
|
|
|
88
86
|
if not isinstance(self.token_reader, TokenReader):
|
|
89
87
|
raise TypeError("token_reader must be an instance of TokenReader")
|
|
90
88
|
|
|
91
|
-
self.well_known_configuration_manager: WellKnownConfigurationManager =
|
|
92
|
-
well_known_configuration_manager
|
|
93
|
-
)
|
|
89
|
+
self.well_known_configuration_manager: WellKnownConfigurationManager = well_known_configuration_manager
|
|
94
90
|
if self.well_known_configuration_manager is None:
|
|
95
91
|
raise ValueError("well_known_configuration_manager must not be None")
|
|
96
|
-
if not isinstance(
|
|
97
|
-
|
|
98
|
-
):
|
|
99
|
-
raise TypeError(
|
|
100
|
-
"well_known_configuration_manager must be an instance of WellKnownConfigurationManager"
|
|
101
|
-
)
|
|
92
|
+
if not isinstance(self.well_known_configuration_manager, WellKnownConfigurationManager):
|
|
93
|
+
raise TypeError("well_known_configuration_manager must be an instance of WellKnownConfigurationManager")
|
|
102
94
|
|
|
103
95
|
self._dcr_manager: DcrManager | None = dcr_manager
|
|
104
96
|
|
|
@@ -109,9 +101,7 @@ class AuthManager:
|
|
|
109
101
|
else OAuthMongoCache(environment_variables=environment_variables)
|
|
110
102
|
)
|
|
111
103
|
|
|
112
|
-
logger.debug(
|
|
113
|
-
f"Initializing AuthManager with cache type {type(self.cache)} cache id: {self.cache.id}"
|
|
114
|
-
)
|
|
104
|
+
logger.debug(f"Initializing AuthManager with cache type {type(self.cache)} cache id: {self.cache.id}")
|
|
115
105
|
# OIDC PKCE setup
|
|
116
106
|
self.redirect_uri = os.getenv("AUTH_REDIRECT_URI")
|
|
117
107
|
if self.redirect_uri is None:
|
|
@@ -119,17 +109,13 @@ class AuthManager:
|
|
|
119
109
|
# https://docs.authlib.org/en/latest/client/frameworks.html#frameworks-clients
|
|
120
110
|
self._oauth: OAuth = OAuth(cache=self.cache)
|
|
121
111
|
self._registered_dynamic_providers: set[str] = set()
|
|
122
|
-
self.auth_configs: List[AuthConfig] = (
|
|
123
|
-
self.auth_config_reader.get_auth_configs_for_all_auth_providers()
|
|
124
|
-
)
|
|
112
|
+
self.auth_configs: List[AuthConfig] = self.auth_config_reader.get_auth_configs_for_all_auth_providers()
|
|
125
113
|
|
|
126
114
|
async def ensure_initialized_async(self) -> None:
|
|
127
115
|
auth_config: AuthConfig
|
|
128
116
|
for auth_config in self.auth_configs:
|
|
129
117
|
if auth_config.well_known_uri:
|
|
130
|
-
await self.well_known_configuration_manager.get_async(
|
|
131
|
-
auth_config=auth_config
|
|
132
|
-
)
|
|
118
|
+
await self.well_known_configuration_manager.get_async(auth_config=auth_config)
|
|
133
119
|
await self.register_dynamic_provider(auth_config=auth_config)
|
|
134
120
|
|
|
135
121
|
async def register_dynamic_provider(
|
|
@@ -162,9 +148,7 @@ class AuthManager:
|
|
|
162
148
|
registration_url=auth_config.registration_url,
|
|
163
149
|
)
|
|
164
150
|
if dcr_result is None or not dcr_result.client_id:
|
|
165
|
-
raise ValueError(
|
|
166
|
-
f"DCR failed to obtain client_id for '{auth_config.auth_provider}'"
|
|
167
|
-
)
|
|
151
|
+
raise ValueError(f"DCR failed to obtain client_id for '{auth_config.auth_provider}'")
|
|
168
152
|
client_id = dcr_result.client_id
|
|
169
153
|
client_secret = dcr_result.client_secret
|
|
170
154
|
logger.info(
|
|
@@ -278,12 +262,24 @@ class AuthManager:
|
|
|
278
262
|
f" with state {state_content} and encoded state {state}"
|
|
279
263
|
)
|
|
280
264
|
|
|
281
|
-
rv: Dict[str, Any] = await client.create_authorization_url(
|
|
282
|
-
redirect_uri=redirect_uri, state=state
|
|
283
|
-
)
|
|
265
|
+
rv: Dict[str, Any] = await client.create_authorization_url(redirect_uri=redirect_uri, state=state)
|
|
284
266
|
logger.debug(f"Authorization URL created: {rv}")
|
|
285
|
-
#
|
|
286
|
-
|
|
267
|
+
# Save OAuth state data (code_verifier, nonce, redirect_uri) to our
|
|
268
|
+
# own cache rather than relying on authlib's save_authorize_data which
|
|
269
|
+
# requires request.session (SessionMiddleware). This allows the
|
|
270
|
+
# callback to retrieve the data without SessionMiddleware.
|
|
271
|
+
state_data: Dict[str, Any] = {"redirect_uri": redirect_uri}
|
|
272
|
+
if "code_verifier" in rv:
|
|
273
|
+
state_data["code_verifier"] = rv["code_verifier"]
|
|
274
|
+
if "nonce" in rv:
|
|
275
|
+
state_data["nonce"] = rv["nonce"]
|
|
276
|
+
cache_key = f"_state_{auth_provider}_{state}"
|
|
277
|
+
await self.cache.set(
|
|
278
|
+
cache_key,
|
|
279
|
+
json.dumps({"data": state_data}),
|
|
280
|
+
expires=OAUTH_STATE_CACHE_TTL_SECONDS,
|
|
281
|
+
)
|
|
282
|
+
logger.debug(f"Saved OAuth state to cache key={cache_key} data={state_data}")
|
|
287
283
|
return cast(str, rv["url"])
|
|
288
284
|
|
|
289
285
|
async def create_oauth_client(self, *, name: str) -> StarletteOAuth2App:
|
|
@@ -327,17 +323,11 @@ class AuthManager:
|
|
|
327
323
|
resp.raise_for_status()
|
|
328
324
|
token_url = resp.json().get("token_endpoint")
|
|
329
325
|
except Exception as e:
|
|
330
|
-
raise AuthorizationNeededException(
|
|
331
|
-
message=f"Failed to discover token endpoint: {e}"
|
|
332
|
-
)
|
|
326
|
+
raise AuthorizationNeededException(message=f"Failed to discover token endpoint: {e}")
|
|
333
327
|
if not token_url and auth_config.issuer:
|
|
334
|
-
token_url = (
|
|
335
|
-
auth_config.issuer.rstrip("/") + "/protocol/openid-connect/token"
|
|
336
|
-
)
|
|
328
|
+
token_url = auth_config.issuer.rstrip("/") + "/protocol/openid-connect/token"
|
|
337
329
|
if not token_url:
|
|
338
|
-
raise AuthorizationNeededException(
|
|
339
|
-
message="No token endpoint found in AuthConfig."
|
|
340
|
-
)
|
|
330
|
+
raise AuthorizationNeededException(message="No token endpoint found in AuthConfig.")
|
|
341
331
|
|
|
342
332
|
# Prepare OAuth2 client
|
|
343
333
|
client_id = auth_config.client_id
|
|
@@ -369,9 +359,7 @@ class AuthManager:
|
|
|
369
359
|
|
|
370
360
|
return access_token
|
|
371
361
|
|
|
372
|
-
def get_auth_config_for_auth_provider(
|
|
373
|
-
self, *, auth_provider: str
|
|
374
|
-
) -> AuthConfig | None:
|
|
362
|
+
def get_auth_config_for_auth_provider(self, *, auth_provider: str) -> AuthConfig | None:
|
|
375
363
|
if not auth_provider:
|
|
376
364
|
raise ValueError("auth_provider must not be empty")
|
|
377
365
|
for auth_config in self.auth_configs:
|
|
@@ -380,9 +368,7 @@ class AuthManager:
|
|
|
380
368
|
return None
|
|
381
369
|
|
|
382
370
|
@staticmethod
|
|
383
|
-
def wait_till_well_known_configuration_available(
|
|
384
|
-
*, auth_config: AuthConfig, timeout_seconds: int = 30
|
|
385
|
-
) -> None:
|
|
371
|
+
def wait_till_well_known_configuration_available(*, auth_config: AuthConfig, timeout_seconds: int = 30) -> None:
|
|
386
372
|
"""
|
|
387
373
|
Wait until the well-known configuration is available for the given AuthConfig.
|
|
388
374
|
|
|
@@ -406,9 +392,7 @@ class AuthManager:
|
|
|
406
392
|
resp = client.get(auth_config.well_known_uri)
|
|
407
393
|
resp.raise_for_status()
|
|
408
394
|
# Successfully fetched the configuration
|
|
409
|
-
logger.info(
|
|
410
|
-
f"Well-known configuration is now available at {auth_config.well_known_uri}"
|
|
411
|
-
)
|
|
395
|
+
logger.info(f"Well-known configuration is now available at {auth_config.well_known_uri}")
|
|
412
396
|
return
|
|
413
397
|
except Exception as e:
|
|
414
398
|
elapsed_time = time.time() - start_time
|
|
@@ -416,7 +400,5 @@ class AuthManager:
|
|
|
416
400
|
raise TimeoutError(
|
|
417
401
|
f"Timed out waiting for well-known configuration at {auth_config.well_known_uri}"
|
|
418
402
|
) from e
|
|
419
|
-
logger.debug(
|
|
420
|
-
f"Well-known configuration not yet available, retrying... ({elapsed_time:.1f}s elapsed)"
|
|
421
|
-
)
|
|
403
|
+
logger.debug(f"Well-known configuration not yet available, retrying... ({elapsed_time:.1f}s elapsed)")
|
|
422
404
|
time.sleep(2) # Wait before retrying
|
|
@@ -14,11 +14,10 @@ class OAuthMemoryCache(OAuthCache):
|
|
|
14
14
|
def id(self) -> uuid.UUID:
|
|
15
15
|
return self.id_
|
|
16
16
|
|
|
17
|
-
_cache: dict[str, str] = {}
|
|
18
|
-
|
|
19
17
|
def __init__(self) -> None:
|
|
20
18
|
"""Initialize the AuthCache."""
|
|
21
19
|
self.id_ = uuid.uuid4()
|
|
20
|
+
self._cache: dict[str, str] = {}
|
|
22
21
|
|
|
23
22
|
@override
|
|
24
23
|
async def delete(self, key: str) -> None:
|
|
@@ -43,30 +43,20 @@ class OAuthMongoCache(OAuthCache):
|
|
|
43
43
|
|
|
44
44
|
"""
|
|
45
45
|
self.id_ = uuid.uuid4()
|
|
46
|
-
self.repository: AsyncBaseRepository[CacheItem] = (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
environment_variables=environment_variables,
|
|
50
|
-
)
|
|
51
|
-
)
|
|
52
|
-
collection_name: str | None = (
|
|
53
|
-
environment_variables.mongo_db_auth_cache_collection_name
|
|
46
|
+
self.repository: AsyncBaseRepository[CacheItem] = RepositoryFactory.get_repository(
|
|
47
|
+
repository_type=environment_variables.oauth_cache,
|
|
48
|
+
environment_variables=environment_variables,
|
|
54
49
|
)
|
|
50
|
+
collection_name: str | None = environment_variables.mongo_db_auth_cache_collection_name
|
|
55
51
|
if collection_name is None:
|
|
56
|
-
raise ValueError(
|
|
57
|
-
"MONGO_DB_AUTH_CACHE_COLLECTION_NAME environment variable must be set"
|
|
58
|
-
)
|
|
52
|
+
raise ValueError("MONGO_DB_AUTH_CACHE_COLLECTION_NAME environment variable must be set")
|
|
59
53
|
self.collection_name: str = collection_name
|
|
60
54
|
|
|
61
55
|
self.environment_variables: AbstractEnvironmentVariables = environment_variables
|
|
62
56
|
if self.environment_variables is None:
|
|
63
|
-
raise ValueError(
|
|
64
|
-
"OAuthMongoCache requires an EnvironmentVariables instance."
|
|
65
|
-
)
|
|
57
|
+
raise ValueError("OAuthMongoCache requires an EnvironmentVariables instance.")
|
|
66
58
|
if not isinstance(self.environment_variables, AbstractEnvironmentVariables):
|
|
67
|
-
raise TypeError(
|
|
68
|
-
"environment_variables must be an instance of EnvironmentVariables"
|
|
69
|
-
)
|
|
59
|
+
raise TypeError("environment_variables must be an instance of EnvironmentVariables")
|
|
70
60
|
|
|
71
61
|
@property
|
|
72
62
|
@override
|
|
@@ -92,9 +82,7 @@ class OAuthMongoCache(OAuthCache):
|
|
|
92
82
|
"key": key,
|
|
93
83
|
},
|
|
94
84
|
)
|
|
95
|
-
disable_delete: bool | None =
|
|
96
|
-
self.environment_variables.mongo_db_cache_disable_delete
|
|
97
|
-
)
|
|
85
|
+
disable_delete: bool | None = self.environment_variables.mongo_db_cache_disable_delete
|
|
98
86
|
if cache_item is not None and cache_item.id is not None:
|
|
99
87
|
# delete the cache item if it exists
|
|
100
88
|
logger.debug(f" ====== Deleting {cache_item.id} =====")
|
|
@@ -131,9 +119,7 @@ class OAuthMongoCache(OAuthCache):
|
|
|
131
119
|
"key": key,
|
|
132
120
|
},
|
|
133
121
|
)
|
|
134
|
-
logger.debug(
|
|
135
|
-
f" ====== For key {key} found {cache_item} default {default} ====="
|
|
136
|
-
)
|
|
122
|
+
logger.debug(f" ====== For key {key} found {cache_item} default {default} =====")
|
|
137
123
|
return cache_item.value if cache_item is not None else default
|
|
138
124
|
|
|
139
125
|
@override
|
|
@@ -166,21 +152,13 @@ class OAuthMongoCache(OAuthCache):
|
|
|
166
152
|
model_class=CacheItem,
|
|
167
153
|
)
|
|
168
154
|
if updated_cache_item is None:
|
|
169
|
-
raise ValueError(
|
|
170
|
-
|
|
171
|
-
)
|
|
172
|
-
logger.debug(
|
|
173
|
-
f"Cache item updated with ID: {updated_cache_item.id} for key: {key} with value: {value}.\n"
|
|
174
|
-
)
|
|
155
|
+
raise ValueError(f"Failed to update cache item with ID: {existing_cache_item_id} for key: {key}")
|
|
156
|
+
logger.debug(f"Cache item updated with ID: {updated_cache_item.id} for key: {key} with value: {value}.\n")
|
|
175
157
|
else:
|
|
176
158
|
logger.debug(f" ====== Creating new cache item {key}: {value} =====")
|
|
177
|
-
cache_item = CacheItem(
|
|
178
|
-
key=key, value=value, created=datetime.now(timezone.utc)
|
|
179
|
-
)
|
|
159
|
+
cache_item = CacheItem(key=key, value=value, created=datetime.now(timezone.utc))
|
|
180
160
|
new_object_id = await self.repository.insert(
|
|
181
161
|
collection_name=self.collection_name,
|
|
182
162
|
model=cache_item,
|
|
183
163
|
)
|
|
184
|
-
logger.debug(
|
|
185
|
-
f"New cache item created with ID: {new_object_id}: {cache_item}"
|
|
186
|
-
)
|
|
164
|
+
logger.debug(f"New cache item created with ID: {new_object_id}: {cache_item}")
|
|
@@ -77,7 +77,6 @@ class AuthConfig(BaseModel):
|
|
|
77
77
|
def _require_client_id_or_registration_url(self) -> Self:
|
|
78
78
|
if not self.client_id and not self.registration_url:
|
|
79
79
|
raise ValueError(
|
|
80
|
-
f"AuthConfig for '{self.auth_provider}' must have either "
|
|
81
|
-
f"client_id or registration_url (for DCR)"
|
|
80
|
+
f"AuthConfig for '{self.auth_provider}' must have either client_id or registration_url (for DCR)"
|
|
82
81
|
)
|
|
83
82
|
return self
|
|
@@ -28,19 +28,13 @@ class AuthConfigReader:
|
|
|
28
28
|
logger.debug("Initializing AuthConfigReader")
|
|
29
29
|
self.environment_variables: AbstractEnvironmentVariables = environment_variables
|
|
30
30
|
if self.environment_variables is None:
|
|
31
|
-
logger.error(
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
raise ValueError(
|
|
35
|
-
"AuthConfigReader requires an EnvironmentVariables instance."
|
|
36
|
-
)
|
|
31
|
+
logger.error("AuthConfigReader initialization failed: environment_variables is None")
|
|
32
|
+
raise ValueError("AuthConfigReader requires an EnvironmentVariables instance.")
|
|
37
33
|
if not isinstance(self.environment_variables, AbstractEnvironmentVariables):
|
|
38
34
|
logger.error(
|
|
39
35
|
f"AuthConfigReader initialization failed: environment_variables is not an instance of AbstractEnvironmentVariables, got {type(environment_variables)}"
|
|
40
36
|
)
|
|
41
|
-
raise TypeError(
|
|
42
|
-
"environment_variables must be an instance of EnvironmentVariables"
|
|
43
|
-
)
|
|
37
|
+
raise TypeError("environment_variables must be an instance of EnvironmentVariables")
|
|
44
38
|
self._auth_configs: list[AuthConfig] | None = None
|
|
45
39
|
# lock to protect first-time initialization of _auth_configs across threads
|
|
46
40
|
self._lock: threading.Lock = threading.Lock()
|
|
@@ -83,9 +77,7 @@ class AuthConfigReader:
|
|
|
83
77
|
)
|
|
84
78
|
if auth_config is not None:
|
|
85
79
|
auth_configs.append(auth_config)
|
|
86
|
-
logger.debug(
|
|
87
|
-
f"Successfully loaded config for provider: {auth_provider}"
|
|
88
|
-
)
|
|
80
|
+
logger.debug(f"Successfully loaded config for provider: {auth_provider}")
|
|
89
81
|
else:
|
|
90
82
|
logger.warning(f"No config found for provider: {auth_provider}")
|
|
91
83
|
# Assign atomically while still under lock
|
|
@@ -124,23 +116,17 @@ class AuthConfigReader:
|
|
|
124
116
|
return
|
|
125
117
|
with self._lock:
|
|
126
118
|
if self._auth_configs is None:
|
|
127
|
-
auth_providers: list[str] | None =
|
|
128
|
-
self.environment_variables.auth_providers
|
|
129
|
-
)
|
|
119
|
+
auth_providers: list[str] | None = self.environment_variables.auth_providers
|
|
130
120
|
if auth_providers is None:
|
|
131
121
|
auth_providers = []
|
|
132
122
|
env_configs: list[AuthConfig] = []
|
|
133
123
|
for auth_provider in auth_providers:
|
|
134
|
-
auth_config = self.read_config_for_auth_provider(
|
|
135
|
-
auth_provider=auth_provider
|
|
136
|
-
)
|
|
124
|
+
auth_config = self.read_config_for_auth_provider(auth_provider=auth_provider)
|
|
137
125
|
if auth_config is not None:
|
|
138
126
|
env_configs.append(auth_config)
|
|
139
127
|
self._auth_configs = env_configs
|
|
140
128
|
|
|
141
|
-
existing_names: set[str] = {
|
|
142
|
-
c.auth_provider.lower() for c in self._auth_configs
|
|
143
|
-
}
|
|
129
|
+
existing_names: set[str] = {c.auth_provider.lower() for c in self._auth_configs}
|
|
144
130
|
for config in configs:
|
|
145
131
|
if config.auth_provider.lower() not in existing_names:
|
|
146
132
|
self._auth_configs.append(config)
|
|
@@ -175,37 +161,23 @@ class AuthConfigReader:
|
|
|
175
161
|
logger.debug(f"Standardized auth provider name to: {auth_provider_upper}")
|
|
176
162
|
# read client_id and client_secret from the environment variables
|
|
177
163
|
auth_client_id: str | None = os.getenv(f"AUTH_CLIENT_ID_{auth_provider_upper}")
|
|
178
|
-
auth_client_secret: str | None = os.getenv(
|
|
179
|
-
f"AUTH_CLIENT_SECRET_{auth_provider_upper}"
|
|
180
|
-
)
|
|
164
|
+
auth_client_secret: str | None = os.getenv(f"AUTH_CLIENT_SECRET_{auth_provider_upper}")
|
|
181
165
|
if auth_client_secret:
|
|
182
166
|
logger.debug(f"Found client secret for provider: {auth_provider_upper}")
|
|
183
167
|
else:
|
|
184
168
|
logger.debug(f"No client secret found for provider: {auth_provider_upper}")
|
|
185
|
-
auth_well_known_uri: str | None = os.getenv(
|
|
186
|
-
f"AUTH_WELL_KNOWN_URI_{auth_provider_upper}"
|
|
187
|
-
)
|
|
169
|
+
auth_well_known_uri: str | None = os.getenv(f"AUTH_WELL_KNOWN_URI_{auth_provider_upper}")
|
|
188
170
|
issuer: str | None = os.getenv(f"AUTH_ISSUER_{auth_provider_upper}")
|
|
189
|
-
logger.debug(
|
|
190
|
-
f"Issuer for {auth_provider_upper}: {issuer if issuer else 'not set'}"
|
|
191
|
-
)
|
|
171
|
+
logger.debug(f"Issuer for {auth_provider_upper}: {issuer if issuer else 'not set'}")
|
|
192
172
|
audience: str | None = os.getenv(f"AUTH_AUDIENCE_{auth_provider_upper}")
|
|
193
173
|
if audience is None:
|
|
194
|
-
logger.error(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
raise ValueError(
|
|
198
|
-
f"AUTH_AUDIENCE_{auth_provider_upper} environment variable must be set"
|
|
199
|
-
)
|
|
200
|
-
friendly_name: str | None = os.getenv(
|
|
201
|
-
f"AUTH_FRIENDLY_NAME_{auth_provider_upper}"
|
|
202
|
-
)
|
|
174
|
+
logger.error(f"AUTH_AUDIENCE_{auth_provider_upper} environment variable is not set")
|
|
175
|
+
raise ValueError(f"AUTH_AUDIENCE_{auth_provider_upper} environment variable must be set")
|
|
176
|
+
friendly_name: str | None = os.getenv(f"AUTH_FRIENDLY_NAME_{auth_provider_upper}")
|
|
203
177
|
if not friendly_name:
|
|
204
178
|
# if no friendly name is set, use the auth_provider as the friendly name
|
|
205
179
|
friendly_name = auth_provider
|
|
206
|
-
logger.debug(
|
|
207
|
-
f"No friendly name set, using auth provider name: {friendly_name}"
|
|
208
|
-
)
|
|
180
|
+
logger.debug(f"No friendly name set, using auth provider name: {friendly_name}")
|
|
209
181
|
else:
|
|
210
182
|
logger.debug(f"Friendly name for {auth_provider}: {friendly_name}")
|
|
211
183
|
|
|
@@ -214,33 +186,21 @@ class AuthConfigReader:
|
|
|
214
186
|
scope = "openid profile email"
|
|
215
187
|
|
|
216
188
|
logger.info(f"Successfully read config for auth provider: {auth_provider}")
|
|
217
|
-
extra_info_text: str | None = os.getenv(
|
|
218
|
-
f"AUTH_EXTRA_INFO_{auth_provider_upper}"
|
|
219
|
-
)
|
|
189
|
+
extra_info_text: str | None = os.getenv(f"AUTH_EXTRA_INFO_{auth_provider_upper}")
|
|
220
190
|
extra_info_dict: dict[str, Any] | None
|
|
221
191
|
if extra_info_text:
|
|
222
192
|
try:
|
|
223
193
|
extra_info_raw: object = json.loads(extra_info_text)
|
|
224
194
|
except json.JSONDecodeError as exc:
|
|
225
|
-
raise ValueError(
|
|
226
|
-
f"Invalid JSON in AUTH_EXTRA_INFO_{auth_provider_upper}: {exc.msg}"
|
|
227
|
-
) from exc
|
|
195
|
+
raise ValueError(f"Invalid JSON in AUTH_EXTRA_INFO_{auth_provider_upper}: {exc.msg}") from exc
|
|
228
196
|
if not isinstance(extra_info_raw, dict):
|
|
229
|
-
raise ValueError(
|
|
230
|
-
f"AUTH_EXTRA_INFO_{auth_provider_upper} must be a JSON object"
|
|
231
|
-
)
|
|
197
|
+
raise ValueError(f"AUTH_EXTRA_INFO_{auth_provider_upper} must be a JSON object")
|
|
232
198
|
extra_info_dict = {str(key): value for key, value in extra_info_raw.items()}
|
|
233
199
|
else:
|
|
234
200
|
extra_info_dict = None
|
|
235
|
-
authorization_endpoint: str | None = os.getenv(
|
|
236
|
-
|
|
237
|
-
)
|
|
238
|
-
token_endpoint: str | None = os.getenv(
|
|
239
|
-
f"AUTH_TOKEN_ENDPOINT_{auth_provider_upper}"
|
|
240
|
-
)
|
|
241
|
-
registration_url: str | None = os.getenv(
|
|
242
|
-
f"AUTH_REGISTRATION_URL_{auth_provider_upper}"
|
|
243
|
-
)
|
|
201
|
+
authorization_endpoint: str | None = os.getenv(f"AUTH_AUTHORIZATION_ENDPOINT_{auth_provider_upper}")
|
|
202
|
+
token_endpoint: str | None = os.getenv(f"AUTH_TOKEN_ENDPOINT_{auth_provider_upper}")
|
|
203
|
+
registration_url: str | None = os.getenv(f"AUTH_REGISTRATION_URL_{auth_provider_upper}")
|
|
244
204
|
|
|
245
205
|
return AuthConfig(
|
|
246
206
|
auth_provider=auth_provider,
|
|
@@ -268,15 +228,11 @@ class AuthConfigReader:
|
|
|
268
228
|
str: The audience for the specified auth provider.
|
|
269
229
|
"""
|
|
270
230
|
logger.debug(f"Getting audience for provider: {auth_provider}")
|
|
271
|
-
auth_config: AuthConfig | None = self.get_config_for_auth_provider(
|
|
272
|
-
auth_provider=auth_provider
|
|
273
|
-
)
|
|
231
|
+
auth_config: AuthConfig | None = self.get_config_for_auth_provider(auth_provider=auth_provider)
|
|
274
232
|
if auth_config is None:
|
|
275
233
|
logger.error(f"AuthConfig for provider {auth_provider} not found")
|
|
276
234
|
raise ValueError(f"AuthConfig for audience {auth_provider} not found.")
|
|
277
|
-
logger.debug(
|
|
278
|
-
f"Found audience for provider {auth_provider}: {auth_config.audience}"
|
|
279
|
-
)
|
|
235
|
+
logger.debug(f"Found audience for provider {auth_provider}: {auth_config.audience}")
|
|
280
236
|
return auth_config.audience
|
|
281
237
|
|
|
282
238
|
def get_provider_for_audience(self, *, audience: str) -> str | None:
|
|
@@ -293,9 +249,7 @@ class AuthConfigReader:
|
|
|
293
249
|
auth_configs: list[AuthConfig] = self.get_auth_configs_for_all_auth_providers()
|
|
294
250
|
for auth_config in auth_configs:
|
|
295
251
|
if auth_config.audience == audience:
|
|
296
|
-
logger.debug(
|
|
297
|
-
f"Found provider for audience {audience}: {auth_config.auth_provider}"
|
|
298
|
-
)
|
|
252
|
+
logger.debug(f"Found provider for audience {audience}: {auth_config.auth_provider}")
|
|
299
253
|
return auth_config.auth_provider
|
|
300
254
|
logger.warning(f"No provider found for audience: {audience}")
|
|
301
255
|
return None
|
|
@@ -314,9 +268,7 @@ class AuthConfigReader:
|
|
|
314
268
|
auth_configs: list[AuthConfig] = self.get_auth_configs_for_all_auth_providers()
|
|
315
269
|
for auth_config in auth_configs:
|
|
316
270
|
if auth_config.client_id == client_id:
|
|
317
|
-
logger.debug(
|
|
318
|
-
f"Found provider for client_id {client_id}: {auth_config.auth_provider}"
|
|
319
|
-
)
|
|
271
|
+
logger.debug(f"Found provider for client_id {client_id}: {auth_config.auth_provider}")
|
|
320
272
|
return auth_config.auth_provider
|
|
321
273
|
logger.warning(f"No provider found for client_id: {client_id}")
|
|
322
274
|
return None
|
|
@@ -73,8 +73,7 @@ class DcrClient:
|
|
|
73
73
|
e.response.text[:500],
|
|
74
74
|
)
|
|
75
75
|
raise ValueError(
|
|
76
|
-
f"DCR registration failed at '{registration_url}' "
|
|
77
|
-
f"with status {e.response.status_code}"
|
|
76
|
+
f"DCR registration failed at '{registration_url}' with status {e.response.status_code}"
|
|
78
77
|
) from e
|
|
79
78
|
dcr_response: dict[str, Any] = response.json()
|
|
80
79
|
|
|
@@ -86,13 +85,11 @@ class DcrClient:
|
|
|
86
85
|
response_keys,
|
|
87
86
|
)
|
|
88
87
|
raise ValueError(
|
|
89
|
-
f"DCR response from '{registration_url}' missing 'client_id'. "
|
|
90
|
-
f"Response keys: {response_keys}"
|
|
88
|
+
f"DCR response from '{registration_url}' missing 'client_id'. Response keys: {response_keys}"
|
|
91
89
|
)
|
|
92
90
|
|
|
93
91
|
logger.info(
|
|
94
|
-
"DCR: Registration successful at '%s' — client_id=%s, "
|
|
95
|
-
"has_secret=%s, expires_at=%s",
|
|
92
|
+
"DCR: Registration successful at '%s' — client_id=%s, has_secret=%s, expires_at=%s",
|
|
96
93
|
registration_url,
|
|
97
94
|
dcr_response["client_id"],
|
|
98
95
|
"client_secret" in dcr_response,
|
|
@@ -32,11 +32,9 @@ class DcrManager:
|
|
|
32
32
|
) -> None:
|
|
33
33
|
self._collection_name = collection_name
|
|
34
34
|
self._redirect_uri = redirect_uri
|
|
35
|
-
self._repository: AsyncBaseRepository[DcrRegistration] = (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
environment_variables=environment_variables,
|
|
39
|
-
)
|
|
35
|
+
self._repository: AsyncBaseRepository[DcrRegistration] = RepositoryFactory.get_repository(
|
|
36
|
+
repository_type=environment_variables.oauth_cache,
|
|
37
|
+
environment_variables=environment_variables,
|
|
40
38
|
)
|
|
41
39
|
self._dcr_client = dcr_client or DcrClient()
|
|
42
40
|
|
|
@@ -53,8 +51,7 @@ class DcrManager:
|
|
|
53
51
|
) -> DcrRegistration | None:
|
|
54
52
|
if client_id:
|
|
55
53
|
logger.info(
|
|
56
|
-
"DCR: Skipping registration for '%s' — client_id already "
|
|
57
|
-
"provided (client_id=%s)",
|
|
54
|
+
"DCR: Skipping registration for '%s' — client_id already provided (client_id=%s)",
|
|
58
55
|
auth_provider,
|
|
59
56
|
client_id,
|
|
60
57
|
)
|
|
@@ -62,13 +59,11 @@ class DcrManager:
|
|
|
62
59
|
|
|
63
60
|
if not registration_url:
|
|
64
61
|
logger.error(
|
|
65
|
-
"DCR: No registration_url and no client_id for '%s' — "
|
|
66
|
-
"cannot resolve credentials",
|
|
62
|
+
"DCR: No registration_url and no client_id for '%s' — cannot resolve credentials",
|
|
67
63
|
auth_provider,
|
|
68
64
|
)
|
|
69
65
|
raise ValueError(
|
|
70
|
-
f"registration_url is required for DCR when client_id is not "
|
|
71
|
-
f"provided (auth_provider='{auth_provider}')"
|
|
66
|
+
f"registration_url is required for DCR when client_id is not provided (auth_provider='{auth_provider}')"
|
|
72
67
|
)
|
|
73
68
|
|
|
74
69
|
validate_url(registration_url)
|
|
@@ -95,16 +90,14 @@ class DcrManager:
|
|
|
95
90
|
|
|
96
91
|
if cached and self._is_expired(cached):
|
|
97
92
|
logger.info(
|
|
98
|
-
"DCR: Cached credentials for '%s' are expired "
|
|
99
|
-
"(client_id=%s, expired_at=%s) — re-registering",
|
|
93
|
+
"DCR: Cached credentials for '%s' are expired (client_id=%s, expired_at=%s) — re-registering",
|
|
100
94
|
auth_provider,
|
|
101
95
|
cached.client_id,
|
|
102
96
|
cached.client_secret_expires_at,
|
|
103
97
|
)
|
|
104
98
|
else:
|
|
105
99
|
logger.info(
|
|
106
|
-
"DCR: No cached credentials found for '%s' — performing "
|
|
107
|
-
"new registration at '%s'",
|
|
100
|
+
"DCR: No cached credentials found for '%s' — performing new registration at '%s'",
|
|
108
101
|
auth_provider,
|
|
109
102
|
registration_url,
|
|
110
103
|
)
|
|
@@ -137,8 +130,7 @@ class DcrManager:
|
|
|
137
130
|
registration_url: str,
|
|
138
131
|
) -> DcrRegistration | None:
|
|
139
132
|
logger.debug(
|
|
140
|
-
"DCR: Querying cache for auth_provider='%s', "
|
|
141
|
-
"registration_url='%s', collection='%s'",
|
|
133
|
+
"DCR: Querying cache for auth_provider='%s', registration_url='%s', collection='%s'",
|
|
142
134
|
auth_provider,
|
|
143
135
|
registration_url,
|
|
144
136
|
self._collection_name,
|