fix(auth): strip redirect_uri from credential_key#5692
Conversation
- Add `redirect_uri = None` to OAuth2 strip block at 3 call sites - tool_auth_handler.py: get_credential_key + legacy variant - auth_tool.py: AuthConfig.get_credential_key - redirect_uri is deployment config, not credential identity - Add hash-stability tests asserting redirect_uri invariance
|
Hi @doughayden , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Can you please fix the failing mypy-diff tests before we can proceed with the review. |
|
@rohityan checking with you before I expand the PR scope to fix the mypy-diff failure... In I propose nesting the full I verified locally: tests pass, manually reproduced mypy-diff comparison is clean. Do you agree with the fix-it-while-we're-here approach? |
- Wrap oauth2 strip block in nested if for mypy narrowing - model_copy widens oauth2 back to OAuth2Auth | Any | None - Eliminates 16 pre-existing union-attr errors plus 2 new ones - Runtime unchanged: deep-copy preserves non-None oauth2
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
This change adds
auth_credential.oauth2.redirect_uri = Noneto the OAuth2 strip block at the three call sites where credential hashing happens.redirect_uriis deployment configuration (which callback URL the auth server should redirect to), not part of the credential identity, so it should be excluded from the hash just as access_token, refresh_token, expires_at, and the other transient OAuth2 fields already are. Without this change, a credential minted under one deployment URL cannot be retrieved when the deployment moves to another.Testing Plan
Unit Tests:
Three new tests, one per affected method. Each constructs two
AuthCredentialinstances that differ only inredirect_uriand asserts the computed key is identical:tests/unittests/tools/openapi_tool/openapi_spec_parser/test_tool_auth_handler.py::test_credential_key_is_stable_across_redirect_uritests/unittests/tools/openapi_tool/openapi_spec_parser/test_tool_auth_handler.py::test_legacy_credential_key_is_stable_across_redirect_uritests/unittests/auth/test_auth_config.py::test_credential_key_is_stable_across_redirect_uriManual End-to-End (E2E) Tests:
A self-contained Runner-based reproduction is at https://github.com/doughayden/adk-issue-examples/tree/main/05-redirect_uri_in_credential_hash. The agent definition (
agent.py) wires up anOpenAPIToolsetagainst a local OAuth2 test server, configured with one redirect_uri value.main.pyconstructs anInMemoryRunner, seeds a real (non-expired) OAuth2 credential into session state under a different redirect_uri's hash, and runs the agent. The--apply-fixflag monkey-patches the proposed fix to demonstrate the resolution end-to-end.Without the fix:
With the fix:
Checklist
Additional context
Scope:
The same strip block exists at three call sites and has the same gap at all three. This PR patches all three. Patching only the tool-level pair (
tool_auth_handler.py) and leaving the framework-level path (auth_tool.py:AuthConfig.get_credential_key) would leave the bug reachable for any consumer that does not work around #5327 withget_auth_config = lambda: None. Patching onlyAuthConfig.get_credential_keyand leaving the tool-level pair would leave the bug reachable on the standard tool-level credential lookup path.Upgrade note:
The credential_key shape changes with this fix:
redirect_uriis no longer included in the hash. OAuth credentials cached in existing session state under the pre-fix key shape become unreachable under the new key. Users should expect a one-time re-auth prompt on the first run after upgrading. Subsequent runs use the new key normally.Related:
ToolAuthHandler._get_existing_credentialrefreshes OAuth2 credentials in memory but doesn't persist them #5329 (refreshed credential persistence, fixed in 218ea76)