Skip to content

Commit 7ba7481

Browse files
PYTHON-5921 Validate OIDC allowed hosts before authenticator reuse (#2801)
Co-authored-by: Steven Silvester <steve.silvester@mongodb.com>
1 parent c9b2331 commit 7ba7481

4 files changed

Lines changed: 46 additions & 6 deletions

File tree

pymongo/asynchronous/auth_oidc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@
5151
def _get_authenticator(
5252
credentials: MongoCredential, address: tuple[str, int]
5353
) -> _OIDCAuthenticator:
54-
if credentials.cache.data:
55-
return credentials.cache.data
56-
5754
# Extract values.
5855
principal_name = credentials.username
5956
properties = credentials.mechanism_properties
@@ -72,6 +69,9 @@ def _get_authenticator(
7269
f"Refusing to connect to {address[0]}, which is not in authOIDCAllowedHosts: {allowed_hosts}"
7370
)
7471

72+
if credentials.cache.data:
73+
return credentials.cache.data
74+
7575
# Get or create the cache data.
7676
credentials.cache.data = _OIDCAuthenticator(username=principal_name, properties=properties)
7777
return credentials.cache.data

pymongo/synchronous/auth_oidc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@
5151
def _get_authenticator(
5252
credentials: MongoCredential, address: tuple[str, int]
5353
) -> _OIDCAuthenticator:
54-
if credentials.cache.data:
55-
return credentials.cache.data
56-
5754
# Extract values.
5855
principal_name = credentials.username
5956
properties = credentials.mechanism_properties
@@ -72,6 +69,9 @@ def _get_authenticator(
7269
f"Refusing to connect to {address[0]}, which is not in authOIDCAllowedHosts: {allowed_hosts}"
7370
)
7471

72+
if credentials.cache.data:
73+
return credentials.cache.data
74+
7575
# Get or create the cache data.
7676
credentials.cache.data = _OIDCAuthenticator(username=principal_name, properties=properties)
7777
return credentials.cache.data

test/asynchronous/test_auth_oidc.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,26 @@ async def fail_point(self, command_args):
117117
await client.close()
118118

119119

120+
class TestOIDCAllowedHostsCache(unittest.TestCase):
121+
class HumanCallback(OIDCCallback):
122+
def fetch(self, context):
123+
return OIDCCallbackResult(access_token="token")
124+
125+
def test_allowed_hosts_checked_before_cached_authenticator_reuse(self):
126+
props = {
127+
"OIDC_HUMAN_CALLBACK": self.HumanCallback(),
128+
"ALLOWED_HOSTS": ["good.example.com"],
129+
}
130+
extra = {"authmechanismproperties": props}
131+
credentials = _build_credentials_tuple("MONGODB-OIDC", None, "user", None, extra, "test")
132+
133+
authenticator = _get_authenticator(credentials, ("good.example.com", 27017))
134+
self.assertIs(authenticator, credentials.cache.data)
135+
136+
with self.assertRaisesRegex(ConfigurationError, "evil.example.com"):
137+
_get_authenticator(credentials, ("evil.example.com", 27017))
138+
139+
120140
class TestAuthOIDCHuman(OIDCTestBase):
121141
uri: str
122142

test/test_auth_oidc.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,26 @@ def fail_point(self, command_args):
117117
client.close()
118118

119119

120+
class TestOIDCAllowedHostsCache(unittest.TestCase):
121+
class HumanCallback(OIDCCallback):
122+
def fetch(self, context):
123+
return OIDCCallbackResult(access_token="token")
124+
125+
def test_allowed_hosts_checked_before_cached_authenticator_reuse(self):
126+
props = {
127+
"OIDC_HUMAN_CALLBACK": self.HumanCallback(),
128+
"ALLOWED_HOSTS": ["good.example.com"],
129+
}
130+
extra = {"authmechanismproperties": props}
131+
credentials = _build_credentials_tuple("MONGODB-OIDC", None, "user", None, extra, "test")
132+
133+
authenticator = _get_authenticator(credentials, ("good.example.com", 27017))
134+
self.assertIs(authenticator, credentials.cache.data)
135+
136+
with self.assertRaisesRegex(ConfigurationError, "evil.example.com"):
137+
_get_authenticator(credentials, ("evil.example.com", 27017))
138+
139+
120140
class TestAuthOIDCHuman(OIDCTestBase):
121141
uri: str
122142

0 commit comments

Comments
 (0)