From 13f7154ac2e52d0611e74ddd8808bf8f6278414e Mon Sep 17 00:00:00 2001 From: Shubham Padkonde Date: Tue, 22 Sep 2026 12:11:52 +0530 Subject: [PATCH] fix(auth): fall back when certificate callbacks return empty credentials --- .../google/auth/aio/transport/mtls.py | 3 ++- .../google/auth/transport/_mtls_helper.py | 3 ++- .../tests/transport/test__mtls_helper.py | 17 ++++++++++++++ .../tests/transport/test_aio_mtls_helper.py | 22 +++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/google-auth/google/auth/aio/transport/mtls.py b/packages/google-auth/google/auth/aio/transport/mtls.py index 12b1b838b6e6..eec9598b675f 100644 --- a/packages/google-auth/google/auth/aio/transport/mtls.py +++ b/packages/google-auth/google/auth/aio/transport/mtls.py @@ -173,7 +173,8 @@ async def get_client_cert_and_key(client_cert_callback=None): cert, key = await result else: cert, key = result - return True, cert, key + if cert and key: + return True, cert, key has_cert, cert, key, _ = await get_client_ssl_credentials() return has_cert, cert, key diff --git a/packages/google-auth/google/auth/transport/_mtls_helper.py b/packages/google-auth/google/auth/transport/_mtls_helper.py index 469932be058c..7561d5fb5713 100644 --- a/packages/google-auth/google/auth/transport/_mtls_helper.py +++ b/packages/google-auth/google/auth/transport/_mtls_helper.py @@ -692,7 +692,8 @@ def get_client_cert_and_key(client_cert_callback=None): """ if client_cert_callback: cert, key = client_cert_callback() - return True, cert, key + if cert and key: + return True, cert, key has_cert, cert, key, _ = get_client_ssl_credentials(generate_encrypted_key=False) return has_cert, cert, key diff --git a/packages/google-auth/tests/transport/test__mtls_helper.py b/packages/google-auth/tests/transport/test__mtls_helper.py index 675f54b46324..bdb9f4fdb1b4 100644 --- a/packages/google-auth/tests/transport/test__mtls_helper.py +++ b/packages/google-auth/tests/transport/test__mtls_helper.py @@ -1952,3 +1952,20 @@ def test_is_mtls_endpoint_true(self, url): ) def test_is_mtls_endpoint_false(self, url): assert _mtls_helper.is_mtls_endpoint(url) is False + + +@pytest.mark.parametrize( + "callback_result", [(None, None), (b"", b""), (b"cert", None), (None, b"key")] +) +@pytest.mark.parametrize( + "default_result", + [(True, b"default-cert", b"default-key", None), (False, None, None, None)], +) +def test_empty_client_cert_callback_uses_default(callback_result, default_result): + callback = mock.Mock(return_value=callback_result) + with mock.patch.object( + _mtls_helper, "get_client_ssl_credentials", return_value=default_result + ) as get_default: + assert _mtls_helper.get_client_cert_and_key(callback) == default_result[:3] + callback.assert_called_once_with() + get_default.assert_called_once_with(generate_encrypted_key=False) diff --git a/packages/google-auth/tests/transport/test_aio_mtls_helper.py b/packages/google-auth/tests/transport/test_aio_mtls_helper.py index 0900225cada0..fc2c01d4349a 100644 --- a/packages/google-auth/tests/transport/test_aio_mtls_helper.py +++ b/packages/google-auth/tests/transport/test_aio_mtls_helper.py @@ -217,3 +217,25 @@ async def test_make_client_cert_ssl_context_setup_error(self, mock_secure_paths) assert "Failed to load client certificate" in str(exc_info.value) assert isinstance(exc_info.value.__cause__, OSError) + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "callback_result", [(None, None), (b"", b""), (b"cert", None), (None, b"key")] +) +@pytest.mark.parametrize( + "default_result", + [(True, b"default-cert", b"default-key", None), (False, None, None, None)], +) +@pytest.mark.parametrize("async_callback", [False, True]) +async def test_empty_client_cert_callback_uses_default( + callback_result, default_result, async_callback +): + callback_type = mock.AsyncMock if async_callback else mock.Mock + callback = callback_type(return_value=callback_result) + with mock.patch.object( + mtls, "get_client_ssl_credentials", return_value=default_result + ) as get_default: + assert await mtls.get_client_cert_and_key(callback) == default_result[:3] + callback.assert_called_once_with() + get_default.assert_awaited_once_with()