Repository navigation
fix(auth): drop a stored credential the server rejected with 401/403 - #7732
Open
inamdarmihir wants to merge 1 commit into
Open
inamdarmihir wants to merge 1 commit into
inamdarmihir wants to merge 1 commit into
Conversation
BaseAuthenticatedTool and AuthenticatedFunctionTool only called request_credential when the credential service held nothing, so a credential that was revoked or expired stayed in the store and was replayed on every call for the rest of the session. When the tool body raises an HTTP 401/403 (an httpx.HTTPStatusError, including one wrapped in another exception), clear the credential kept in the credential service so the next call goes through request_credential again. Static API key / HTTP credentials, custom auth schemes and runs without a credential service are left alone, and the original error still propagates. McpTool inherits this through BaseAuthenticatedTool. Subclasses that report an unauthorized outcome as a return value can call the new _discard_rejected_credential hook. Fixes google#3016
|
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. |
Contributor
Author
|
@googlebot I signed it! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
Problem
BaseAuthenticatedToolandAuthenticatedFunctionToolonly callrequest_credentialwhen the credential service holds nothing. If a stored credential is later revoked or turns out to be wrong (bad password, token for the wrong account) and the API answers 401/403, it stays in the store and is replayed on every call for the rest of the session. The user can never re-authenticate.Solution
CredentialManager.discard_stored_credential(context)clears the credential kept in the credential service.BaseAuthenticatedTool.run_asyncandAuthenticatedFunctionTool.run_asynccatch an exception from the tool body. If it is an HTTP 401/403 (httpx.HTTPStatusError, also found through__cause__,__context__and exception groups), they discard the stored credential and re-raise the original error. The next call then goes throughrequest_credential.BaseAuthenticatedTool._discard_rejected_credentialfor subclasses that report an unauthorized outcome as a return value.McpToolinherits the behavior throughBaseAuthenticatedTool.RestApiToolkeeps its existingToolAuthHandler401 handling and is untouched.Testing Plan
Unit Tests:
New
tests/unittests/tools/test_authenticated_tool_reauth.py(11 tests): 401 and 403 clear the credential and the next call requests it again (forBaseAuthenticatedTool,AuthenticatedFunctionToolandMcpToolthrough a mocked session), a wrapped error is detected, and 404 / 500 /ValueError/ successful calls leave the credential alone, as does a static API key credential.srcchanges stashed: 5 failed, 6 passed.tests/unittests/toolsplustests/unittests/authgive 3660 passed, 1 skipped.Manual End-to-End (E2E) Tests:
Not run: tests outside
tests/unittests/toolsandtests/unittests/auth.Checklist
Additional context
Limits, so reviewers know what is and is not covered:
httpx.HTTPStatusError. Tools that return 401/403 as a value, and MCP failures with nohttpxcause (isError=trueresults, a bareMcpError), are not detected here. The new hook is there for them.BaseCredentialServicehas no compare-and-delete, so a late 401 from a call using an old token could clear a freshly refreshed credential.Authored by Mihir Inamdar.