Validate OIDC allowed hosts before cache reuse

This commit is contained in:
NguyenCong2k 2026-05-13 10:01:00 +07:00
parent 0adf6df131
commit 0c58649d55
4 changed files with 46 additions and 6 deletions

View File

@ -49,9 +49,6 @@ _IS_SYNC = False
def _get_authenticator(
credentials: MongoCredential, address: tuple[str, int]
) -> _OIDCAuthenticator:
if credentials.cache.data:
return credentials.cache.data
# Extract values.
principal_name = credentials.username
properties = credentials.mechanism_properties
@ -70,6 +67,9 @@ def _get_authenticator(
f"Refusing to connect to {address[0]}, which is not in authOIDCAllowedHosts: {allowed_hosts}"
)
if credentials.cache.data:
return credentials.cache.data
# Get or create the cache data.
credentials.cache.data = _OIDCAuthenticator(username=principal_name, properties=properties)
return credentials.cache.data

View File

@ -49,9 +49,6 @@ _IS_SYNC = True
def _get_authenticator(
credentials: MongoCredential, address: tuple[str, int]
) -> _OIDCAuthenticator:
if credentials.cache.data:
return credentials.cache.data
# Extract values.
principal_name = credentials.username
properties = credentials.mechanism_properties
@ -70,6 +67,9 @@ def _get_authenticator(
f"Refusing to connect to {address[0]}, which is not in authOIDCAllowedHosts: {allowed_hosts}"
)
if credentials.cache.data:
return credentials.cache.data
# Get or create the cache data.
credentials.cache.data = _OIDCAuthenticator(username=principal_name, properties=properties)
return credentials.cache.data

View File

@ -117,6 +117,26 @@ class OIDCTestBase(AsyncPyMongoTestCase):
await client.close()
class TestOIDCAllowedHostsCache(unittest.TestCase):
class HumanCallback(OIDCCallback):
def fetch(self, context):
return OIDCCallbackResult(access_token="token")
def test_allowed_hosts_checked_before_cached_authenticator_reuse(self):
props = {
"OIDC_HUMAN_CALLBACK": self.HumanCallback(),
"ALLOWED_HOSTS": ["good.example.com"],
}
extra = {"authmechanismproperties": props}
credentials = _build_credentials_tuple("MONGODB-OIDC", None, "user", None, extra, "test")
authenticator = _get_authenticator(credentials, ("good.example.com", 27017))
self.assertIs(authenticator, credentials.cache.data)
with self.assertRaisesRegex(ConfigurationError, "evil.example.com"):
_get_authenticator(credentials, ("evil.example.com", 27017))
class TestAuthOIDCHuman(OIDCTestBase):
uri: str

View File

@ -117,6 +117,26 @@ class OIDCTestBase(PyMongoTestCase):
client.close()
class TestOIDCAllowedHostsCache(unittest.TestCase):
class HumanCallback(OIDCCallback):
def fetch(self, context):
return OIDCCallbackResult(access_token="token")
def test_allowed_hosts_checked_before_cached_authenticator_reuse(self):
props = {
"OIDC_HUMAN_CALLBACK": self.HumanCallback(),
"ALLOWED_HOSTS": ["good.example.com"],
}
extra = {"authmechanismproperties": props}
credentials = _build_credentials_tuple("MONGODB-OIDC", None, "user", None, extra, "test")
authenticator = _get_authenticator(credentials, ("good.example.com", 27017))
self.assertIs(authenticator, credentials.cache.data)
with self.assertRaisesRegex(ConfigurationError, "evil.example.com"):
_get_authenticator(credentials, ("evil.example.com", 27017))
class TestAuthOIDCHuman(OIDCTestBase):
uri: str