Fix: default an OpenID Connect scheme with no grantTypesSupported to the authorization-code grant - #865
Open
AmaadMartin wants to merge 2 commits into
Open
Fix: default an OpenID Connect scheme with no grantTypesSupported to the authorization-code grant#865AmaadMartin wants to merge 2 commits into
AmaadMartin wants to merge 2 commits into
Conversation
added 2 commits
August 9, 2026 06:34
…real scheme Both cases named themselves OpenIdConnect but passed a bare object with no type discriminant, so they were not valid OpenIdConnectWithConfig values. Both assertions are unchanged.
…orization_code OpenID Connect Discovery 1.0 section 3 makes grant_types_supported OPTIONAL and defaults it to ["authorization_code", "implicit"]. determineGrantType() sniffed that field instead of the scheme type, so a provider that omits it returned undefined, exchange() logged "Unsupported OAuth2 grant type: undefined" and no token was ever requested. Gate the branch on the type discriminant, which also matches adk-python _determine_grant_type().
AmaadMartin
force-pushed
the
fix/oidc-default-authorization-code-grant
branch
from
August 9, 2026 13:35
342e46e to
9130d19
Compare
AmaadMartin
changed the base branch from
fix/oauth2-grant-type-scheme-guards
to
main
August 9, 2026 13:35
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.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
Link to an existing issue (if applicable):
Or, if no issue exists, describe the change:
Problem:
determineGrantType()selected the OpenID Connect grant by sniffing thegrantTypesSupportedproperty. OpenID Connect Discovery 1.0 section 3 makes that field OPTIONAL and defaults it to["authorization_code", "implicit"](https://openid.net/specs/openid-connect-discovery-1_0.html), so a spec-compliant provider that omits it gotundefined.exchange()then loggedUnsupported OAuth2 grant type: undefinedand returned the credential unexchanged, with no token and no error.Solution: Gate the OpenID Connect branch on the
typediscriminant and default to the authorization-code grant.grantTypesSupportednow only ever selectsCLIENT_CREDENTIALS. This matches adk-python_determine_grant_type()insrc/google/adk/auth/exchanger/oauth2_credential_exchanger.py, which branches on the scheme type and defaults the same way. Parity wins here because "does an OIDC tool acquire a token" is observable across the language boundary. The source diff is 2 changed lines and a comment; theflowsbranch above it is untouched.Overlap with #773. That PR refactors the same function to use a new
isOpenIdConnectScheme()guard, and it also narrows theflowsbranch. It does not make this behaviour change. I first stacked this PR on it, then rebased ontomainso the diff shows only this change. Whichever lands second needs a one-function textual merge. Collision check run before writing any code:gh pr list --state open --limit 100plusgh pr diff --name-onlyon every adjacent auth PR (#772, #774, #845, #848, #862, #864). Only #773 touchesoauth2_credential_exchanger.ts.Behaviour change, no API change. Nothing is added to
core/src/index.tsorcore/src/common.ts. Two directions:grantTypesSupportednow attempts a real token exchange. A caller who passes an incomplete credential and ignores the result now seesCredentialExchangeErrorwhere it previously saw a silent no-op. That is the intended trade. No error message changes.grantTypesSupportedno longer resolves to a grant type. It is not a validOpenIdConnectWithConfig, which requirestype: 'openIdConnect', so this reaches untyped JavaScript callers and hand-built test doubles only.Blast radius for the new throw:
AuthHandler.parseAndStoreAuthResponse()andToolAuthHandler.prepareAuthCredentials()viaAutoAuthCredentialExchanger. Neither is modified here.Two existing fixtures corrected, in their own commit (5557d11). Both
determineGrantTypeOpenIdConnect cases named themselves OpenIdConnect but passed{grantTypesSupported: [...]} as AuthScheme, with notype. They only passed because the function sniffed a property. Both assertions are unchanged, and that commit is green on its own. No test is deleted, skipped, or weakened.Testing Plan
Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.
Unit Tests:
[x] I have added or updated unit tests for my change.
[x] All unit tests pass locally.
Five tests added: three for
determineGrantType(omittedgrantTypesSupported, emptygrantTypesSupported, and anapiKeyscheme to prove the branch did not widen) and two forexchange()(the token request now happens, and an incomplete credential now raisesCredentialExchangeError).CI is green on all four
run-testsjobs. The firstwindows-latestattempt failed on two integration tests that this diff does not touch (tests/integration/a2a/basic/a2a_agent_test.tsserver startup, and a 40s timeout intests/integration/app_loader/app_loader_test.ts). Both passed on re-run, andubuntu-latestandmacos-latestpassed on the first attempt.npm run ts:checkreports pre-existing errors in unrelated test files (core/test/plugins/logging_plugin_test.ts,core/test/agents/instructions_test.tsand others). #764 tracks that. Neither changed file appears in the output.Coverage of
core/src/auth/oauth2/oauth2_credential_exchanger.tsundercore/test/auth: 100% statements, 100% lines, 100% functions, 96% branches. The two uncovered branches are in the pre-existingauthResponseUristate-checktry/catch, outside this diff.Proof the tests can fail. I restored the old gate (
(authScheme as OpenIdConnectWithConfig).grantTypesSupported) and reran the file. Three tests failed:The empty-array test passes either way by design:
[]is truthy, so it pins behaviour the fix does not change.Manual End-to-End (E2E) Tests:
No E2E test is added. A real check needs a live OpenID Provider that omits
grant_types_supported, andfetchOAuth2Tokens()rejects loopback and non-HTTPS endpoints, so no local server can stand in for one.I ran the built package directly, with no mocks, against an OIDC scheme with no
grantTypesSupportedand a loopback token endpoint:The SSRF rejection proves the token request is now issued. Before this change the same call logged
Unsupported OAuth2 grant type: undefinedand resolved withwasExchanged: false. To repeat it against a real provider, build anOpenIdConnectWithConfigfrom a discovery document withgrant_types_supporteddeleted, and confirm a POST reaches the token endpoint.Checklist
[x] I have read the CONTRIBUTING.md document.
[x] I have performed a self-review of my own code.
[x] I have commented my code, particularly in hard-to-understand areas.
[x] I have added tests that prove my fix is effective or that my feature works.
[x] New and existing unit tests pass locally with my changes.