Skip to content

Commit 97e91d0

Browse files
chore: Refactor mTLS handling for unauthorized responses
chore: Refactor mTLS handling for unauthorized responses
1 parent d734731 commit 97e91d0

1 file changed

Lines changed: 75 additions & 52 deletions

File tree

  • packages/google-auth/google/auth/aio/transport

packages/google-auth/google/auth/aio/transport/sessions.py

Lines changed: 75 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -318,61 +318,84 @@ async def request(
318318
url, method, data, headers, actual_timeout, **kwargs
319319
)
320320
)
321-
if response.status_code == http_client.UNAUTHORIZED:
322-
if getattr(self, "is_mtls", False) and any(
323-
prefix in url for prefix in MTLS_URL_PREFIXES
324-
):
325-
# Snapshot the stale certificate state BEFORE acquiring the lock.
326-
# This represents the cert that caused the 401 rejection.
327-
stale_cert = self._cached_cert
328-
329-
# Wait in line to acquire the lock
330-
async with self._mtls_rotation_lock:
331-
# Check Did another coroutine already reconfigure mTLS
332-
if self._cached_cert != stale_cert:
333-
# Yes! Another request already updated the channel
334-
pass
335-
else:
336-
try:
337-
(
338-
call_cert_bytes,
339-
call_key_bytes,
340-
cached_fingerprint,
341-
current_cert_fingerprint,
342-
) = await mtls._run_in_executor(
343-
google.auth.transport._mtls_helper.check_parameters_for_unauthorized_response,
344-
self._cached_cert,
345-
)
346-
if cached_fingerprint != current_cert_fingerprint:
347-
try:
348-
_LOGGER.info(
349-
"Client certificate has changed, reconfiguring mTLS "
350-
"channel."
351-
)
352-
if self._mtls_init_task and self._mtls_init_task.done():
353-
self._mtls_init_task = None
354-
await self.configure_mtls_channel(
355-
lambda: (call_cert_bytes, call_key_bytes)
356-
)
357-
continue
358-
except Exception as e:
359-
_LOGGER.error("Failed to reconfigure mTLS channel: %s", e)
360-
raise exceptions.MutualTLSChannelError(
361-
"Failed to reconfigure mTLS channel"
362-
) from e
363-
else:
364-
_LOGGER.info(
365-
"Skipping reconfiguration of mTLS channel because the client"
366-
" certificate has not changed."
367-
)
368-
except Exception as e:
369-
_LOGGER.warning(
370-
"Failed to check client certificate parameters: %s. Proceeding with original response.",
371-
e,
372-
)
373321

374322
if response.status_code not in transport.DEFAULT_RETRYABLE_STATUS_CODES:
375323
break
324+
325+
if response.status_code == http_client.UNAUTHORIZED:
326+
_auth_retry_count = kwargs.pop("_auth_retry_count", 0)
327+
if _auth_retry_count < 2:
328+
is_streaming = data is not None and isinstance(data, (collections.abc.Iterator, collections.abc.AsyncIterable)) or hasattr(data, "read")
329+
if getattr(self, "is_mtls", False) and any(
330+
prefix in url for prefix in MTLS_URL_PREFIXES
331+
):
332+
# Snapshot the stale certificate state BEFORE acquiring the lock.
333+
# This represents the cert that caused the 401 rejection.
334+
stale_cert = self._cached_cert
335+
336+
# Wait in line to acquire the lock
337+
async with self._mtls_rotation_lock:
338+
# Check Did another coroutine already reconfigure mTLS
339+
if self._cached_cert != stale_cert:
340+
# Yes! Another request already updated the channel
341+
pass
342+
else:
343+
try:
344+
(
345+
call_cert_bytes,
346+
call_key_bytes,
347+
cached_fingerprint,
348+
current_cert_fingerprint,
349+
) = await mtls._run_in_executor(
350+
google.auth.transport._mtls_helper.check_parameters_for_unauthorized_response,
351+
self._cached_cert,
352+
)
353+
if cached_fingerprint != current_cert_fingerprint:
354+
try:
355+
_LOGGER.info(
356+
"Client certificate has changed, reconfiguring mTLS "
357+
"channel."
358+
)
359+
if self._mtls_init_task and self._mtls_init_task.done():
360+
self._mtls_init_task = None
361+
await self.configure_mtls_channel(
362+
lambda: (call_cert_bytes, call_key_bytes)
363+
)
364+
continue
365+
except Exception as e:
366+
_LOGGER.error("Failed to reconfigure mTLS channel: %s", e)
367+
raise exceptions.MutualTLSChannelError(
368+
"Failed to reconfigure mTLS channel"
369+
) from e
370+
else:
371+
_LOGGER.info(
372+
"Skipping reconfiguration of mTLS channel because the client"
373+
" certificate has not changed."
374+
)
375+
except Exception as e:
376+
_LOGGER.warning(
377+
"Failed to check client certificate parameters: %s. Proceeding with original response.",
378+
e,
379+
)
380+
if is_streaming:
381+
return response
382+
if hasattr(response, "close"):
383+
if asyncio.iscoroutinefunction(response.close):
384+
await response.close()
385+
else:
386+
response.close()
387+
await self._credentials.refresh(self._auth_request)
388+
kwargs["_auth_retry_count"] = _auth_retry_count + 1
389+
return await self.request(
390+
method,
391+
url,
392+
data=data,
393+
headers=headers,
394+
max_allowed_time=max_allowed_time,
395+
timeout=timeout,
396+
total_attempts=total_attempts,
397+
**kwargs
398+
)
376399
return response
377400

378401
@functools.wraps(request)

0 commit comments

Comments
 (0)