Skip to content

fix(auth): serialize credential lifecycle by key#6478

Open
tylergibbs1 wants to merge 1 commit into
google:mainfrom
tylergibbs1:agent/serialize-credential-lifecycle
Open

fix(auth): serialize credential lifecycle by key#6478
tylergibbs1 wants to merge 1 commit into
google:mainfrom
tylergibbs1:agent/serialize-credential-lifecycle

Conversation

@tylergibbs1

Copy link
Copy Markdown

Summary

  • serialize credential validation, loading, exchange, refresh, and saving for concurrent requests that share a credential key
  • keep unrelated credential keys concurrent
  • scope locks to their asyncio event loop and hold them weakly so completed credentials and closed loops do not accumulate in memory

Root cause

CredentialManager.get_auth_credential() performed the load → exchange/refresh → save lifecycle without coordination. Concurrent managers could therefore load the same stale credential, independently exchange or refresh it, and race while saving the result.

The new key-scoped lock keeps that lifecycle atomic within an event loop. A waiter reloads the credential after acquiring the lock, so it observes the result saved by the preceding request instead of repeating the external operation.

Closes #6475.

User impact

Concurrent agent/tool calls using the same OAuth credential no longer duplicate token exchange or refresh requests. Calls using different credential keys are not serialized.

Testing plan

  • pytest tests/unittests/auth — 195 passed
  • full Python 3.11 unit suite using the CI exclusions — 8,831 passed, 64 skipped, 18 xfailed, 1 xpassed
  • focused test_credential_manager.py tox runs on Python 3.10, 3.12, 3.13, and 3.14 — all passed
  • pre-commit run --files src/google/adk/auth/credential_manager.py tests/unittests/auth/test_credential_manager.py
  • uv build

@google-cla

google-cla Bot commented Jul 25, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@tylergibbs1
tylergibbs1 marked this pull request as ready for review July 25, 2026 15:20
@adk-bot adk-bot added the core [Component] This issue is related to the core interface and implementation label Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core [Component] This issue is related to the core interface and implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Race condition in CredentialManager.get_auth_credential() — missing concurrency control in credential exchange/refresh/save lifecycle

3 participants