oidcauthlib 3.0.5__tar.gz → 3.0.7__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.7/MANIFEST.in +1 -0
- {oidcauthlib-3.0.5/oidcauthlib.egg-info → oidcauthlib-3.0.7}/PKG-INFO +4 -14
- oidcauthlib-3.0.7/VERSION +1 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/auth_helper.py +2 -6
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/auth_manager.py +34 -53
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/cache/oauth_mongo_cache.py +13 -35
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/config/auth_config.py +1 -2
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/config/auth_config_reader.py +24 -72
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/dcr/dcr_client.py +3 -6
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/dcr/dcr_manager.py +11 -21
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/dcr/dcr_registration.py +3 -9
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/fastapi_auth_manager.py +83 -34
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/middleware/request_scope_middleware.py +4 -11
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/middleware/token_reader_middleware.py +7 -21
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/models/auth.py +2 -6
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/models/cache_item.py +1 -3
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/models/client_key_set.py +2 -6
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/models/token.py +6 -26
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/repository/base_repository.py +2 -6
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/repository/memory/memory_repository.py +2 -8
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/repository/mongo/mongo_repository.py +14 -42
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/repository/repository_factory.py +2 -6
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/routers/auth_router.py +9 -29
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/token_reader.py +8 -26
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/well_known_configuration/auth_server_metadata_discovery.py +1 -2
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/well_known_configuration/well_known_configuration_cache.py +35 -92
- oidcauthlib-3.0.7/oidcauthlib/auth/well_known_configuration/well_known_configuration_cache_result.py +9 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/well_known_configuration/well_known_configuration_manager.py +2 -6
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/container/oidc_authlib_container_factory.py +5 -15
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/storage/mongo_gridfs_db.py +26 -77
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/storage/mongo_storage_factory.py +5 -13
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/storage/storage_factory_creator.py +2 -5
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/environment/oidc_environment_variables.py +8 -24
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/logger/logging_response.py +2 -6
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/mongo_url_utils.py +1 -3
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/url_validator.py +33 -11
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7/oidcauthlib.egg-info}/PKG-INFO +4 -14
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib.egg-info/SOURCES.txt +2 -50
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib.egg-info/top_level.txt +0 -1
- oidcauthlib-3.0.7/pyproject.toml +107 -0
- oidcauthlib-3.0.7/setup.cfg +4 -0
- oidcauthlib-3.0.5/MANIFEST.in +0 -6
- oidcauthlib-3.0.5/Makefile +0 -85
- oidcauthlib-3.0.5/VERSION +0 -1
- oidcauthlib-3.0.5/oidcauthlib/auth/well_known_configuration/well_known_configuration_cache_result.py +0 -15
- oidcauthlib-3.0.5/oidcauthlib.egg-info/not-zip-safe +0 -1
- oidcauthlib-3.0.5/setup.cfg +0 -29
- oidcauthlib-3.0.5/setup.py +0 -82
- oidcauthlib-3.0.5/tests/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/cache/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/cache/test_oauth_memory_cache.py +0 -26
- oidcauthlib-3.0.5/tests/auth/config/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/config/test_auth_config.py +0 -72
- oidcauthlib-3.0.5/tests/auth/config/test_auth_config_reader.py +0 -91
- oidcauthlib-3.0.5/tests/auth/config/test_auth_config_reader_register.py +0 -200
- oidcauthlib-3.0.5/tests/auth/config/test_auth_config_reader_thread_safety.py +0 -127
- oidcauthlib-3.0.5/tests/auth/conftest.py +0 -14
- oidcauthlib-3.0.5/tests/auth/dcr/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/dcr/test_dcr_client.py +0 -129
- oidcauthlib-3.0.5/tests/auth/dcr/test_dcr_manager.py +0 -198
- oidcauthlib-3.0.5/tests/auth/middleware/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/middleware/test_request_scope_middleware.py +0 -188
- oidcauthlib-3.0.5/tests/auth/middleware/test_token_reader_middleware.py +0 -671
- oidcauthlib-3.0.5/tests/auth/models/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/models/test_auth.py +0 -43
- oidcauthlib-3.0.5/tests/auth/models/test_base_db_model.py +0 -70
- oidcauthlib-3.0.5/tests/auth/models/test_cache_item.py +0 -17
- oidcauthlib-3.0.5/tests/auth/models/test_token.py +0 -48
- oidcauthlib-3.0.5/tests/auth/repository/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/repository/memory/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/repository/memory/test_memory_repository.py +0 -156
- oidcauthlib-3.0.5/tests/auth/repository/mongo/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/repository/mongo/test_mongo_repository.py +0 -912
- oidcauthlib-3.0.5/tests/auth/repository/mongo/test_mongo_repository_real.py +0 -178
- oidcauthlib-3.0.5/tests/auth/test_auth_helper.py +0 -26
- oidcauthlib-3.0.5/tests/auth/test_auth_helper2.py +0 -33
- oidcauthlib-3.0.5/tests/auth/test_auth_manager.py +0 -514
- oidcauthlib-3.0.5/tests/auth/test_register_dynamic_provider.py +0 -348
- oidcauthlib-3.0.5/tests/auth/well_known_configuration/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/auth/well_known_configuration/test_auth_server_metadata_discovery.py +0 -184
- oidcauthlib-3.0.5/tests/auth/well_known_configuration/test_well_known_configuration_cache.py +0 -393
- oidcauthlib-3.0.5/tests/auth/well_known_configuration/test_well_known_configuration_manager.py +0 -174
- oidcauthlib-3.0.5/tests/conftest.py +0 -130
- oidcauthlib-3.0.5/tests/storage/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/storage/test_mongo_gridfs_db.py +0 -378
- oidcauthlib-3.0.5/tests/storage/test_mongo_gridfs_race_setup.py +0 -70
- oidcauthlib-3.0.5/tests/storage/test_mongo_store_factory.py +0 -516
- oidcauthlib-3.0.5/tests/storage/test_storage_factory_security.py +0 -498
- oidcauthlib-3.0.5/tests/utilities/__init__.py +0 -0
- oidcauthlib-3.0.5/tests/utilities/test_cached.py +0 -52
- oidcauthlib-3.0.5/tests/utilities/test_mongo_url_utils.py +0 -30
- oidcauthlib-3.0.5/tests/utilities/test_url_validator.py +0 -155
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/LICENSE +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/README.md +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/cache/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/cache/oauth_cache.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/cache/oauth_memory_cache.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/config/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/dcr/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/exceptions/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/exceptions/authorization_bearer_token_expired_exception.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/exceptions/authorization_bearer_token_invalid_exception.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/exceptions/authorization_bearer_token_missing_exception.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/exceptions/authorization_needed_exception.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/middleware/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/models/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/models/base_db_model.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/repository/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/repository/memory/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/repository/mongo/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/routers/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/well_known_configuration/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/auth/well_known_configuration/auth_server_metadata.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/container/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/open_telemetry/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/open_telemetry/attribute_names.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/open_telemetry/span_names.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/py.typed +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/storage/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/storage/cache_to_collection_mapper.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/storage/memory_storage_factory.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/storage/mongo_gridfs_exception.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/storage/storage_factory.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/cached.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/environment/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/environment/abstract_environment_variables.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/logger/__init__.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/logger/log_levels.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib/utilities/logger/logging_transport.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib.egg-info/dependency_links.txt +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/oidcauthlib.egg-info/requires.txt +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/tests/test_mongo_url_utils.py +0 -0
- {oidcauthlib-3.0.5 → oidcauthlib-3.0.7}/tests/test_simple.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include VERSION
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oidcauthlib
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.7
|
|
4
4
|
Summary: oidcauthlib
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Author-email: Imran Qureshi <imran.qureshi@bwell.com>
|
|
6
|
+
License-Expression: 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
|
|
12
11
|
Requires-Python: >=3.12
|
|
13
12
|
Description-Content-Type: text/markdown
|
|
@@ -23,15 +22,6 @@ Requires-Dist: starlette>=0.49.1
|
|
|
23
22
|
Requires-Dist: py-key-value-aio[memory,mongodb,pydantic,redis]>=0.4.4
|
|
24
23
|
Requires-Dist: opentelemetry-api>=1.39.1
|
|
25
24
|
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
25
|
Dynamic: license-file
|
|
33
|
-
Dynamic: requires-dist
|
|
34
|
-
Dynamic: requires-python
|
|
35
|
-
Dynamic: summary
|
|
36
26
|
|
|
37
27
|
# oidcauthlib
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.0.7
|
|
@@ -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
|
|
@@ -33,6 +34,7 @@ from oidcauthlib.utilities.logger.log_levels import SRC_LOG_LEVELS
|
|
|
33
34
|
from oidcauthlib.utilities.logger.logging_transport import (
|
|
34
35
|
LoggingTransport,
|
|
35
36
|
)
|
|
37
|
+
from oidcauthlib.utilities.url_validator import validate_url
|
|
36
38
|
|
|
37
39
|
logger = logging.getLogger(__name__)
|
|
38
40
|
logger.setLevel(SRC_LOG_LEVELS["AUTH"])
|
|
@@ -69,17 +71,13 @@ class AuthManager:
|
|
|
69
71
|
if self.environment_variables is None:
|
|
70
72
|
raise ValueError("environment_variables must not be None")
|
|
71
73
|
if not isinstance(self.environment_variables, AbstractEnvironmentVariables):
|
|
72
|
-
raise TypeError(
|
|
73
|
-
"environment_variables must be an instance of EnvironmentVariables"
|
|
74
|
-
)
|
|
74
|
+
raise TypeError("environment_variables must be an instance of EnvironmentVariables")
|
|
75
75
|
|
|
76
76
|
self.auth_config_reader: AuthConfigReader = auth_config_reader
|
|
77
77
|
if self.auth_config_reader is None:
|
|
78
78
|
raise ValueError("auth_config_reader must not be None")
|
|
79
79
|
if not isinstance(self.auth_config_reader, AuthConfigReader):
|
|
80
|
-
raise TypeError(
|
|
81
|
-
"auth_config_reader must be an instance of AuthConfigReader"
|
|
82
|
-
)
|
|
80
|
+
raise TypeError("auth_config_reader must be an instance of AuthConfigReader")
|
|
83
81
|
|
|
84
82
|
self.token_reader: TokenReader = token_reader
|
|
85
83
|
if self.token_reader is None:
|
|
@@ -87,17 +85,11 @@ class AuthManager:
|
|
|
87
85
|
if not isinstance(self.token_reader, TokenReader):
|
|
88
86
|
raise TypeError("token_reader must be an instance of TokenReader")
|
|
89
87
|
|
|
90
|
-
self.well_known_configuration_manager: WellKnownConfigurationManager =
|
|
91
|
-
well_known_configuration_manager
|
|
92
|
-
)
|
|
88
|
+
self.well_known_configuration_manager: WellKnownConfigurationManager = well_known_configuration_manager
|
|
93
89
|
if self.well_known_configuration_manager is None:
|
|
94
90
|
raise ValueError("well_known_configuration_manager must not be None")
|
|
95
|
-
if not isinstance(
|
|
96
|
-
|
|
97
|
-
):
|
|
98
|
-
raise TypeError(
|
|
99
|
-
"well_known_configuration_manager must be an instance of WellKnownConfigurationManager"
|
|
100
|
-
)
|
|
91
|
+
if not isinstance(self.well_known_configuration_manager, WellKnownConfigurationManager):
|
|
92
|
+
raise TypeError("well_known_configuration_manager must be an instance of WellKnownConfigurationManager")
|
|
101
93
|
|
|
102
94
|
self._dcr_manager: DcrManager | None = dcr_manager
|
|
103
95
|
|
|
@@ -108,9 +100,7 @@ class AuthManager:
|
|
|
108
100
|
else OAuthMongoCache(environment_variables=environment_variables)
|
|
109
101
|
)
|
|
110
102
|
|
|
111
|
-
logger.debug(
|
|
112
|
-
f"Initializing AuthManager with cache type {type(self.cache)} cache id: {self.cache.id}"
|
|
113
|
-
)
|
|
103
|
+
logger.debug(f"Initializing AuthManager with cache type {type(self.cache)} cache id: {self.cache.id}")
|
|
114
104
|
# OIDC PKCE setup
|
|
115
105
|
self.redirect_uri = os.getenv("AUTH_REDIRECT_URI")
|
|
116
106
|
if self.redirect_uri is None:
|
|
@@ -118,17 +108,13 @@ class AuthManager:
|
|
|
118
108
|
# https://docs.authlib.org/en/latest/client/frameworks.html#frameworks-clients
|
|
119
109
|
self._oauth: OAuth = OAuth(cache=self.cache)
|
|
120
110
|
self._registered_dynamic_providers: set[str] = set()
|
|
121
|
-
self.auth_configs: List[AuthConfig] = (
|
|
122
|
-
self.auth_config_reader.get_auth_configs_for_all_auth_providers()
|
|
123
|
-
)
|
|
111
|
+
self.auth_configs: List[AuthConfig] = self.auth_config_reader.get_auth_configs_for_all_auth_providers()
|
|
124
112
|
|
|
125
113
|
async def ensure_initialized_async(self) -> None:
|
|
126
114
|
auth_config: AuthConfig
|
|
127
115
|
for auth_config in self.auth_configs:
|
|
128
116
|
if auth_config.well_known_uri:
|
|
129
|
-
await self.well_known_configuration_manager.get_async(
|
|
130
|
-
auth_config=auth_config
|
|
131
|
-
)
|
|
117
|
+
await self.well_known_configuration_manager.get_async(auth_config=auth_config)
|
|
132
118
|
await self.register_dynamic_provider(auth_config=auth_config)
|
|
133
119
|
|
|
134
120
|
async def register_dynamic_provider(
|
|
@@ -161,9 +147,7 @@ class AuthManager:
|
|
|
161
147
|
registration_url=auth_config.registration_url,
|
|
162
148
|
)
|
|
163
149
|
if dcr_result is None or not dcr_result.client_id:
|
|
164
|
-
raise ValueError(
|
|
165
|
-
f"DCR failed to obtain client_id for '{auth_config.auth_provider}'"
|
|
166
|
-
)
|
|
150
|
+
raise ValueError(f"DCR failed to obtain client_id for '{auth_config.auth_provider}'")
|
|
167
151
|
client_id = dcr_result.client_id
|
|
168
152
|
client_secret = dcr_result.client_secret
|
|
169
153
|
logger.info(
|
|
@@ -199,9 +183,12 @@ class AuthManager:
|
|
|
199
183
|
}
|
|
200
184
|
|
|
201
185
|
if auth_config.authorization_endpoint and auth_config.token_endpoint:
|
|
186
|
+
validate_url(auth_config.authorization_endpoint)
|
|
187
|
+
validate_url(auth_config.token_endpoint)
|
|
202
188
|
register_kwargs["authorize_url"] = auth_config.authorization_endpoint
|
|
203
189
|
register_kwargs["access_token_url"] = auth_config.token_endpoint
|
|
204
190
|
elif auth_config.well_known_uri:
|
|
191
|
+
validate_url(auth_config.well_known_uri)
|
|
205
192
|
register_kwargs["server_metadata_url"] = auth_config.well_known_uri
|
|
206
193
|
else:
|
|
207
194
|
raise ValueError(
|
|
@@ -274,12 +261,20 @@ class AuthManager:
|
|
|
274
261
|
f" with state {state_content} and encoded state {state}"
|
|
275
262
|
)
|
|
276
263
|
|
|
277
|
-
rv: Dict[str, Any] = await client.create_authorization_url(
|
|
278
|
-
redirect_uri=redirect_uri, state=state
|
|
279
|
-
)
|
|
264
|
+
rv: Dict[str, Any] = await client.create_authorization_url(redirect_uri=redirect_uri, state=state)
|
|
280
265
|
logger.debug(f"Authorization URL created: {rv}")
|
|
281
|
-
#
|
|
282
|
-
|
|
266
|
+
# Save OAuth state data (code_verifier, nonce, redirect_uri) to our
|
|
267
|
+
# own cache rather than relying on authlib's save_authorize_data which
|
|
268
|
+
# requires request.session (SessionMiddleware). This allows the
|
|
269
|
+
# callback to retrieve the data without SessionMiddleware.
|
|
270
|
+
state_data: Dict[str, Any] = {"redirect_uri": redirect_uri}
|
|
271
|
+
if "code_verifier" in rv:
|
|
272
|
+
state_data["code_verifier"] = rv["code_verifier"]
|
|
273
|
+
if "nonce" in rv:
|
|
274
|
+
state_data["nonce"] = rv["nonce"]
|
|
275
|
+
cache_key = f"_state_{auth_provider}_{state}"
|
|
276
|
+
await self.cache.set(cache_key, json.dumps({"data": state_data}))
|
|
277
|
+
logger.debug(f"Saved OAuth state to cache key={cache_key} data={state_data}")
|
|
283
278
|
return cast(str, rv["url"])
|
|
284
279
|
|
|
285
280
|
async def create_oauth_client(self, *, name: str) -> StarletteOAuth2App:
|
|
@@ -323,17 +318,11 @@ class AuthManager:
|
|
|
323
318
|
resp.raise_for_status()
|
|
324
319
|
token_url = resp.json().get("token_endpoint")
|
|
325
320
|
except Exception as e:
|
|
326
|
-
raise AuthorizationNeededException(
|
|
327
|
-
message=f"Failed to discover token endpoint: {e}"
|
|
328
|
-
)
|
|
321
|
+
raise AuthorizationNeededException(message=f"Failed to discover token endpoint: {e}")
|
|
329
322
|
if not token_url and auth_config.issuer:
|
|
330
|
-
token_url = (
|
|
331
|
-
auth_config.issuer.rstrip("/") + "/protocol/openid-connect/token"
|
|
332
|
-
)
|
|
323
|
+
token_url = auth_config.issuer.rstrip("/") + "/protocol/openid-connect/token"
|
|
333
324
|
if not token_url:
|
|
334
|
-
raise AuthorizationNeededException(
|
|
335
|
-
message="No token endpoint found in AuthConfig."
|
|
336
|
-
)
|
|
325
|
+
raise AuthorizationNeededException(message="No token endpoint found in AuthConfig.")
|
|
337
326
|
|
|
338
327
|
# Prepare OAuth2 client
|
|
339
328
|
client_id = auth_config.client_id
|
|
@@ -365,9 +354,7 @@ class AuthManager:
|
|
|
365
354
|
|
|
366
355
|
return access_token
|
|
367
356
|
|
|
368
|
-
def get_auth_config_for_auth_provider(
|
|
369
|
-
self, *, auth_provider: str
|
|
370
|
-
) -> AuthConfig | None:
|
|
357
|
+
def get_auth_config_for_auth_provider(self, *, auth_provider: str) -> AuthConfig | None:
|
|
371
358
|
if not auth_provider:
|
|
372
359
|
raise ValueError("auth_provider must not be empty")
|
|
373
360
|
for auth_config in self.auth_configs:
|
|
@@ -376,9 +363,7 @@ class AuthManager:
|
|
|
376
363
|
return None
|
|
377
364
|
|
|
378
365
|
@staticmethod
|
|
379
|
-
def wait_till_well_known_configuration_available(
|
|
380
|
-
*, auth_config: AuthConfig, timeout_seconds: int = 30
|
|
381
|
-
) -> None:
|
|
366
|
+
def wait_till_well_known_configuration_available(*, auth_config: AuthConfig, timeout_seconds: int = 30) -> None:
|
|
382
367
|
"""
|
|
383
368
|
Wait until the well-known configuration is available for the given AuthConfig.
|
|
384
369
|
|
|
@@ -402,9 +387,7 @@ class AuthManager:
|
|
|
402
387
|
resp = client.get(auth_config.well_known_uri)
|
|
403
388
|
resp.raise_for_status()
|
|
404
389
|
# Successfully fetched the configuration
|
|
405
|
-
logger.info(
|
|
406
|
-
f"Well-known configuration is now available at {auth_config.well_known_uri}"
|
|
407
|
-
)
|
|
390
|
+
logger.info(f"Well-known configuration is now available at {auth_config.well_known_uri}")
|
|
408
391
|
return
|
|
409
392
|
except Exception as e:
|
|
410
393
|
elapsed_time = time.time() - start_time
|
|
@@ -412,7 +395,5 @@ class AuthManager:
|
|
|
412
395
|
raise TimeoutError(
|
|
413
396
|
f"Timed out waiting for well-known configuration at {auth_config.well_known_uri}"
|
|
414
397
|
) from e
|
|
415
|
-
logger.debug(
|
|
416
|
-
f"Well-known configuration not yet available, retrying... ({elapsed_time:.1f}s elapsed)"
|
|
417
|
-
)
|
|
398
|
+
logger.debug(f"Well-known configuration not yet available, retrying... ({elapsed_time:.1f}s elapsed)")
|
|
418
399
|
time.sleep(2) # Wait before retrying
|
|
@@ -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)
|
|
@@ -86,8 +81,7 @@ class DcrManager:
|
|
|
86
81
|
|
|
87
82
|
if cached and not self._is_expired(cached):
|
|
88
83
|
logger.info(
|
|
89
|
-
"DCR: Using cached credentials for '%s' — client_id=%s, "
|
|
90
|
-
"expires_at=%s",
|
|
84
|
+
"DCR: Using cached credentials for '%s' — client_id=%s, expires_at=%s",
|
|
91
85
|
auth_provider,
|
|
92
86
|
cached.client_id,
|
|
93
87
|
cached.client_secret_expires_at or "never",
|
|
@@ -96,16 +90,14 @@ class DcrManager:
|
|
|
96
90
|
|
|
97
91
|
if cached and self._is_expired(cached):
|
|
98
92
|
logger.info(
|
|
99
|
-
"DCR: Cached credentials for '%s' are expired "
|
|
100
|
-
"(client_id=%s, expired_at=%s) — re-registering",
|
|
93
|
+
"DCR: Cached credentials for '%s' are expired (client_id=%s, expired_at=%s) — re-registering",
|
|
101
94
|
auth_provider,
|
|
102
95
|
cached.client_id,
|
|
103
96
|
cached.client_secret_expires_at,
|
|
104
97
|
)
|
|
105
98
|
else:
|
|
106
99
|
logger.info(
|
|
107
|
-
"DCR: No cached credentials found for '%s' — performing "
|
|
108
|
-
"new registration at '%s'",
|
|
100
|
+
"DCR: No cached credentials found for '%s' — performing new registration at '%s'",
|
|
109
101
|
auth_provider,
|
|
110
102
|
registration_url,
|
|
111
103
|
)
|
|
@@ -138,8 +130,7 @@ class DcrManager:
|
|
|
138
130
|
registration_url: str,
|
|
139
131
|
) -> DcrRegistration | None:
|
|
140
132
|
logger.debug(
|
|
141
|
-
"DCR: Querying cache for auth_provider='%s', "
|
|
142
|
-
"registration_url='%s', collection='%s'",
|
|
133
|
+
"DCR: Querying cache for auth_provider='%s', registration_url='%s', collection='%s'",
|
|
143
134
|
auth_provider,
|
|
144
135
|
registration_url,
|
|
145
136
|
self._collection_name,
|
|
@@ -154,8 +145,7 @@ class DcrManager:
|
|
|
154
145
|
)
|
|
155
146
|
if results:
|
|
156
147
|
logger.debug(
|
|
157
|
-
"DCR: Cache hit for '%s' — found %d result(s), "
|
|
158
|
-
"client_id=%s",
|
|
148
|
+
"DCR: Cache hit for '%s' — found %d result(s), client_id=%s",
|
|
159
149
|
auth_provider,
|
|
160
150
|
len(results),
|
|
161
151
|
results[0].client_id,
|