Repository navigation
fix(connectors): persist the scopes Google actually granted on reconnect - #3865
Merged
Merged
Conversation
… the ones asked for Reconnecting to add a scope left the connection record claiming less authority than the refresh token carries, so coverage checks kept demanding a reconnect the user had already completed. include_granted_scopes (#3786) made over-grant the normal case on every reconnect, which turned this from a latent edge case into live behavior. The token response's scope set is now persisted as returned. Per-agent grants still narrow to what that flow requested. Closes #3851
4 tasks
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.
Reconnecting a Google account to add a second scope still ended with GAIA asking for yet another reconnect. Google hands back every scope the account already granted, but GAIA threw away anything it hadn't asked for in that particular flow, so the stored connection understated what the refresh token could actually do and the coverage check kept reporting missing scopes. The connection now records the scope set the token really carries, so a scope granted on an earlier connect stays usable. What each agent may use is unchanged — agent grants are still limited to the scopes that flow asked for.
Closes #3851
Test plan
python -m pytest tests/unit/connectors/ -xpassespython util/lint.py --allpassesgaia connectors listshows both scope sets and noCONNECTION_MISSING_SCOPESon a Gmail call🔍 Technical details
Root cause:
_resolve_granted_scopes(src/gaia/connectors/flow.py:543) intersected the token response'sscopewith the originally-requested list, so any scope Google folded in viainclude_granted_scopes=true(#3786) was dropped beforesave_connection.check_scopes(src/gaia/connectors/api.py:239) then read the truncated record and raisedCONNECTION_MISSING_SCOPESfor scopes the token demonstrably held.Change: the returned scope list is persisted as-is (order-preserving, deduped). The two other branches are untouched — an absent
scopestill means "as requested" per RFC 6749 §5.1, an explicitly empty one still means nothing was granted. Both the loopback exchange (flow.py:613) and the device-code path (flow.py:842) pick this up.Grant narrowing is unaffected:
_commit_grants_for_providerfilters each agent's requested scopes against the granted set, so a wider granted set cannot widen a grant. Covered by the existingtest_commit_grants_intersects_token_scopes.Verified:
tests/unit/connectors/— 806 passed. Newtest_wider_returned_scope_is_what_gets_persistedfails on the pre-fix implementation (the extra scope is missing from the record) and passes after. Lint:black/isortclean on the touched files; the three pre-existingutil/lint.py --allfailures reproduce unchanged onmainand are in files this PR does not touch.Docs:
docs/security/connections.mdxgained one sentence distinguishing the connection record (token's full authority) from grants (per-agent subset) — the existing grant sentence there was already correct.