Skip to content

feat(core): add OAuth2 Authorization Code auth provider for A2A agents#21496

Merged
adamfweidman merged 11 commits intomainfrom
feat/oauth2-a2a-auth-provider
Mar 10, 2026
Merged

feat(core): add OAuth2 Authorization Code auth provider for A2A agents#21496
adamfweidman merged 11 commits intomainfrom
feat/oauth2-a2a-auth-provider

Conversation

@SandyTao520
Copy link
Contributor

@SandyTao520 SandyTao520 commented Mar 7, 2026

Summary

Adds OAuth2 Authorization Code + PKCE authentication support for A2A remote agents, built on shared OAuth flow primitives extracted from the existing MCP OAuth provider.

Details

This PR consists of three logical parts:

1. Extract shared OAuth flow primitives (utils/oauth-flow.ts)

Refactors the MCP OAuth provider to extract reusable OAuth primitives (PKCE generation, authorization URL building, token exchange, token refresh, callback server) into utils/oauth-flow.ts. The MCP provider is updated to use these shared primitives, with no behavioral changes.

2. Add OAuth2 auth provider for A2A agents

Introduces OAuth2AuthProvider that implements the full OAuth 2.0 Authorization Code + PKCE flow for A2A remote agents:

  • Browser-based interactive authentication with user consent
  • Automatic token refresh using refresh tokens
  • Persistent token storage in ~/.gemini/a2a-oauth-tokens.json (separate from MCP tokens)
  • OAuth URL discovery from agent card securitySchemes (with fallback to user config)
  • Retry logic on 401/403 responses

Also adds:

  • Zod schema and frontmatter parsing for the oauth2 auth type in agent definitions
  • Wiring through the auth provider factory, agent registry, and remote invocation

3. Fix agent card fetch with auth credentials

Separates the fetch implementation used for agent card resolution from API transport calls. By default, the agent card is fetched without auth headers to avoid servers that reject unexpected credentials (e.g., 400 errors). Auth is only sent to the card endpoint when agent_card_requires_auth is explicitly set to true.

Commits

  • refactor(core): extract shared OAuth flow primitives from MCPOAuthProvider
  • fix(core): validate JSON token response before casting
  • fix(core): add clientId guard and unit tests for shared OAuth flow
  • feat(core): add OAuth2 Authorization Code auth provider for A2A agents
  • fix(core): use unauthenticated fetch for A2A agent card resolution

Related Issues

Fixes #17600

How to Validate

  1. Run all affected tests:
    npm test -w @google/gemini-cli-core -- src/utils/oauth-flow.test.ts
    npm test -w @google/gemini-cli-core -- src/agents/auth-provider/oauth2-provider.test.ts
    npm test -w @google/gemini-cli-core -- src/agents/auth-provider/factory.test.ts
    npm test -w @google/gemini-cli-core -- src/agents/agentLoader.test.ts
    npm test -w @google/gemini-cli-core -- src/agents/a2a-client-manager.test.ts
    
  2. Verify the MCP OAuth provider still works (it now delegates to shared primitives).
  3. Manual: Configure a remote agent with auth.type: oauth2 and valid Google OAuth credentials. Verify the browser-based auth flow completes and tokens are persisted.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

…vider

Extract generic OAuth 2.0 Authorization Code + PKCE logic into a shared
oauth-flow.ts module so both MCP and A2A authentication providers can
reuse it. MCPOAuthProvider now delegates to these shared utilities while
retaining MCP-specific logic (discovery, dynamic registration, resource
parameter handling).

Part of #17600
Address review feedback: validate that JSON-parsed response contains a
string access_token before treating it as an OAuthTokenResponse. If the
JSON doesn't contain the expected field, fall through to form-urlencoded
parsing instead of blindly casting.
- Replace unsafe clientId! non-null assertion in
  MCPOAuthProvider.refreshAccessToken with an explicit validation guard
- Add 42 dedicated unit tests for oauth-flow.ts covering all exported
  functions: generatePKCEParams, getPortFromUrl, buildAuthorizationUrl,
  startCallbackServer, exchangeCodeForToken, and refreshAccessToken
Implement OAuth2AuthProvider with PKCE support for A2A remote agents,
enabling browser-based OAuth 2.0 Authorization Code flow with automatic
token refresh and persistent storage.

Key changes:
- OAuth2AuthProvider: full auth code + PKCE flow with token caching
- Agent card URL discovery: fetches OAuth endpoints from agent card
- Separate token storage: a2a-oauth-tokens.json (not MCP's file)
- Zod schema + frontmatter support for oauth2 auth type
- Factory wiring with dynamic import to avoid module graph issues
Separate the fetch implementations used for agent card resolution vs.
API transport calls. By default, the agent card is fetched without auth
headers to avoid servers that reject unexpected credentials (e.g. 400).
Auth is only sent to the card endpoint when agent_card_requires_auth is
explicitly set to true in the agent definition.
@SandyTao520 SandyTao520 requested a review from a team as a code owner March 7, 2026 00:08
@gemini-cli
Copy link
Contributor

gemini-cli bot commented Mar 7, 2026

Hi there! Thank you for your contribution to Gemini CLI.

To improve our contribution process and better track changes, we now require all pull requests to be associated with an existing issue, as announced in our recent discussion and as detailed in our CONTRIBUTING.md.

This pull request is being closed because it is not currently linked to an issue. Once you have updated the description of this PR to link an issue (e.g., by adding Fixes #123 or Related to #123), it will be automatically reopened.

How to link an issue:
Add a keyword followed by the issue number (e.g., Fixes #123) in the description of your pull request. For more details on supported keywords and how linking works, please refer to the GitHub Documentation on linking pull requests to issues.

Thank you for your understanding and for being a part of our community!

@gemini-cli gemini-cli bot closed this Mar 7, 2026
@gemini-cli
Copy link
Contributor

gemini-cli bot commented Mar 7, 2026

Hi @SandyTao520, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.

We're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: Improving Our Contribution Process & Introducing New Guidelines.

Key Update: Starting January 26, 2026, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.

Thank you for your understanding and for being a part of our community!

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the authentication capabilities for A2A remote agents by integrating the OAuth 2.0 Authorization Code flow with PKCE. It achieves this by refactoring existing OAuth logic into reusable primitives and introducing a dedicated provider for A2A agents. The changes also improve the robustness of agent card fetching by handling authentication requirements more intelligently, preventing potential credential rejection issues.

Highlights

  • OAuth2 Authorization Code Provider for A2A Agents: Introduced a new OAuth2AuthProvider to enable OAuth 2.0 Authorization Code + PKCE authentication for A2A (Agent-to-Agent) remote agents, supporting interactive browser-based flows, automatic token refresh, and persistent token storage.
  • Shared OAuth Flow Primitives: Extracted common OAuth flow logic (PKCE generation, authorization URL building, token exchange, token refresh, callback server) into a new utils/oauth-flow.ts module, which is now reused by both the new A2A OAuth2 provider and the existing MCP OAuth provider.
  • Agent Card Fetch Authentication Logic: Implemented a fix to separate agent card resolution fetches from API transport calls, ensuring agent cards are fetched without authentication headers by default to prevent issues with servers rejecting unexpected credentials. Authentication is only applied if agent_card_requires_auth is explicitly set to true.
  • OAuth2 Configuration and Discovery: Added Zod schema validation and frontmatter parsing for oauth2 auth types in agent definitions, allowing OAuth URLs to be configured directly or discovered from agent card securitySchemes.
Changelog
  • packages/core/src/agents/a2a-client-manager.test.ts
    • Updated test descriptions for clarity regarding authentication handler usage.
    • Added new tests to verify that the card resolver does not use authenticated fetch by default and correctly uses it when agentCardRequiresAuth is true.
  • packages/core/src/agents/a2a-client-manager.ts
    • Introduced LoadAgentOptions interface to allow specifying if an agent card requires authentication.
    • Modified loadAgent method to accept LoadAgentOptions and conditionally use an authenticated fetch for agent card resolution.
  • packages/core/src/agents/agentLoader.test.ts
    • Added new test cases to validate parsing of remote agents with various OAuth2 authentication configurations, including minimal and full setups, and rejection of invalid URLs.
  • packages/core/src/agents/agentLoader.ts
    • Extended FrontmatterAuthConfig to include oauth2 as a valid authentication type.
    • Added new fields (client_id, client_secret, scopes, authorization_url, token_url) to FrontmatterAuthConfig for OAuth2 configuration.
    • Integrated oauth2AuthSchema into authConfigSchema using discriminatedUnion.
    • Implemented conversion logic in convertFrontmatterAuthToConfig to handle oauth2 authentication types.
  • packages/core/src/agents/auth-provider/factory.test.ts
    • Mocked MCPOAuthTokenStorage to prevent disk I/O during tests.
    • Added tests to ensure A2AAuthProviderFactory correctly creates OAuth2AuthProvider instances for oauth2 configurations, including scenarios with agent card defaults and missing agent names.
  • packages/core/src/agents/auth-provider/factory.ts
    • Added agentCardUrl to CreateAuthProviderOptions interface.
    • Implemented dynamic import and instantiation of OAuth2AuthProvider when the authentication type is oauth2.
  • packages/core/src/agents/auth-provider/oauth2-provider.test.ts
    • Added a new test file to thoroughly test the OAuth2AuthProvider class, covering constructor behavior, token initialization, header generation, token refresh, interactive authentication, retry logic, token persistence, and agent card integration for URL discovery.
  • packages/core/src/agents/auth-provider/oauth2-provider.ts
    • Added a new file defining the OAuth2AuthProvider class, which implements OAuth 2.0 Authorization Code flow with PKCE for A2A agents.
    • Implemented logic for loading, refreshing, and interactively acquiring OAuth tokens.
    • Included retry mechanisms for 401/403 responses and token persistence to a dedicated file.
    • Added functionality to discover OAuth URLs from agent cards if not explicitly configured.
  • packages/core/src/agents/auth-provider/types.ts
    • Extended OAuth2AuthConfig interface to include optional authorization_url and token_url properties.
  • packages/core/src/agents/registry.test.ts
    • Updated A2AAuthProviderFactory.create calls to pass agentCardUrl.
    • Modified A2AClientManager.loadAgent calls to pass agentCardRequiresAuth option.
  • packages/core/src/agents/registry.ts
    • Modified AgentRegistry to pass agentCardUrl to A2AAuthProviderFactory.create.
    • Updated A2AClientManager.loadAgent call to include agentCardRequiresAuth from the agent definition.
  • packages/core/src/agents/remote-invocation.test.ts
    • Updated A2AAuthProviderFactory.create calls to pass agentCardUrl.
  • packages/core/src/agents/remote-invocation.ts
    • Modified RemoteAgentInvocation to pass agentCardUrl to A2AAuthProviderFactory.create.
  • packages/core/src/config/storage.ts
    • Added getA2AOAuthTokensPath() method to provide a separate file path for A2A OAuth tokens.
  • packages/core/src/mcp/oauth-provider.ts
    • Removed duplicated OAuth flow logic (PKCE generation, callback server, URL building, token exchange, token refresh) by importing and utilizing shared utilities from ../utils/oauth-flow.js.
    • Re-exported OAuth types from ../utils/oauth-flow.js for backward compatibility.
    • Refactored refreshAccessToken to use the shared refreshAccessTokenShared function.
    • Refactored authenticate to use shared generatePKCEParams, startCallbackServer, getPortFromUrl, buildAuthorizationUrl, and exchangeCodeForToken functions.
  • packages/core/src/mcp/oauth-token-storage.ts
    • Modified the constructor to accept an optional tokenFilePath argument, allowing custom storage locations for OAuth tokens.
    • Updated getTokenFilePath to use the provided customTokenFilePath or fall back to the default MCP path.
  • packages/core/src/utils/oauth-flow.test.ts
    • Added a new test file to cover the functionality of the shared OAuth flow utilities, including PKCE generation, port extraction, authorization URL building, callback server operation, and token exchange/refresh mechanisms.
  • packages/core/src/utils/oauth-flow.ts
    • Added a new file containing shared, protocol-agnostic utilities for OAuth 2.0 Authorization Code flow with PKCE.
    • Exported functions for generatePKCEParams, startCallbackServer, getPortFromUrl, buildAuthorizationUrl, exchangeCodeForToken, and refreshAccessToken.
    • Defined interfaces OAuthFlowConfig, OAuthRefreshConfig, PKCEParams, OAuthAuthorizationResponse, and OAuthTokenResponse.
Activity
  • The pull request introduces a new feature to support OAuth2 Authorization Code authentication for A2A agents.
  • It includes a significant refactoring effort to extract shared OAuth flow primitives, making the authentication logic more modular and reusable.
  • Several commits address fixes related to JSON token response validation and client ID guards for the shared OAuth flow.
  • A specific fix was implemented to ensure agent card resolution uses unauthenticated fetches by default, improving compatibility.
  • The author has added and updated numerous tests across multiple files to cover the new OAuth2 provider and the refactored shared utilities, indicating thorough testing.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the authentication capabilities for A2A (Agent-to-Agent) remote agents by integrating OAuth2 Authorization Code with PKCE. It centralizes common OAuth logic into a shared utility, enabling more robust and secure communication for agents while also refining how agent cards are fetched to improve compatibility and reduce authentication-related errors.

Highlights

  • Shared OAuth Flow Primitives: Extracted reusable OAuth primitives (PKCE generation, authorization URL building, token exchange, token refresh, callback server) into a new utils/oauth-flow.ts module. The existing MCP OAuth provider was refactored to utilize these shared primitives without changing its behavior.
  • OAuth2 Authorization Code Provider for A2A Agents: Introduced a new OAuth2AuthProvider that implements the full OAuth 2.0 Authorization Code + PKCE flow for A2A remote agents. This includes browser-based interactive authentication, automatic token refresh, persistent token storage in ~/.gemini/a2a-oauth-tokens.json, OAuth URL discovery from agent card securitySchemes, and retry logic for 401/403 responses.
  • Agent Card Fetch with Auth Credentials: Separated the fetch implementation for agent card resolution from API transport calls. Agent cards are now fetched without authentication headers by default to prevent issues with servers rejecting unexpected credentials, with an option to explicitly require authentication via agent_card_requires_auth.
Changelog
  • packages/core/src/agents/a2a-client-manager.test.ts
    • Updated test cases to verify agent card fetch behavior with and without authentication.
  • packages/core/src/agents/a2a-client-manager.ts
    • Added LoadAgentOptions interface and modified loadAgent to conditionally use authenticated fetch for agent card resolution.
  • packages/core/src/agents/agentLoader.test.ts
    • Added new test cases to validate parsing of remote agents with OAuth2 authentication configurations.
  • packages/core/src/agents/agentLoader.ts
    • Extended FrontmatterAuthConfig and authConfigSchema to support OAuth2 authentication parameters and updated convertFrontmatterAuthToConfig to handle OAuth2.
  • packages/core/src/agents/auth-provider/factory.test.ts
    • Added mock for MCPOAuthTokenStorage and new test cases to verify the creation of OAuth2AuthProvider.
  • packages/core/src/agents/auth-provider/factory.ts
    • Modified A2AAuthProviderFactory to dynamically import and create OAuth2AuthProvider instances.
  • packages/core/src/agents/auth-provider/oauth2-provider.test.ts
    • Added comprehensive unit tests for the new OAuth2AuthProvider covering initialization, token handling, retry logic, and agent card integration.
  • packages/core/src/agents/auth-provider/oauth2-provider.ts
    • Implemented OAuth2AuthProvider to handle OAuth 2.0 Authorization Code flow with PKCE for A2A agents, including token storage, refresh, and interactive authentication.
  • packages/core/src/agents/auth-provider/types.ts
    • Extended OAuth2AuthConfig interface to include authorization_url and token_url properties.
  • packages/core/src/agents/registry.test.ts
    • Updated AgentRegistry test to pass agentCardUrl to the auth provider factory.
  • packages/core/src/agents/registry.ts
    • Modified AgentRegistry to pass agentCardUrl and agentCardRequiresAuth to the A2AClientManager and A2AAuthProviderFactory.
  • packages/core/src/agents/remote-invocation.test.ts
    • Updated RemoteAgentInvocation test to pass agentCardUrl to the auth provider factory.
  • packages/core/src/agents/remote-invocation.ts
    • Modified RemoteAgentInvocation to pass agentCardUrl to the A2AAuthProviderFactory.
  • packages/core/src/config/storage.ts
    • Added a new static method getA2AOAuthTokensPath to define the storage path for A2A OAuth tokens.
  • packages/core/src/mcp/oauth-provider.ts
    • Refactored MCPOAuthProvider to use shared OAuth flow primitives from utils/oauth-flow.ts, removing duplicated logic.
  • packages/core/src/mcp/oauth-token-storage.ts
    • Modified MCPOAuthTokenStorage to accept an optional tokenFilePath in its constructor, allowing for protocol-specific token storage.
  • packages/core/src/utils/oauth-flow.test.ts
    • Added new unit tests for the shared OAuth flow utilities, covering PKCE generation, callback server, authorization URL building, and token exchange/refresh.
  • packages/core/src/utils/oauth-flow.ts
    • Created new shared utilities for OAuth 2.0 Authorization Code flow with PKCE, including functions for PKCE generation, callback server, authorization URL building, and token exchange/refresh.
Activity
  • No specific reviewer comments or activity have been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@SandyTao520 SandyTao520 reopened this Mar 7, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces OAuth2 Authorization Code + PKCE authentication for A2A remote agents. The implementation is robust, featuring a comprehensive new OAuth2AuthProvider that handles the full interactive flow, token refresh, and persistent storage. A significant part of this work involved refactoring shared OAuth logic from the existing MCP provider into a new, well-tested utils/oauth-flow.ts module, which greatly improves code structure and reusability. The changes also include a fix to agent card resolution to avoid sending authentication headers by default. The code quality is high, with thorough testing and good design patterns. I have no major concerns.

@github-actions
Copy link

github-actions bot commented Mar 7, 2026

Size Change: +11.7 kB (+0.04%)

Total Size: 26.2 MB

Filename Size Change
./bundle/gemini.js 25.7 MB +11.7 kB (+0.05%)
ℹ️ View Unchanged
Filename Size
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 221 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 227 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 11.5 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B
./bundle/sandbox-macos-permissive-open.sb 890 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB
./bundle/sandbox-macos-strict-open.sb 4.82 kB
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB

compressed-size-action

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces OAuth2 Authorization Code + PKCE support for A2A agents, involving refactoring existing OAuth logic into shared primitives, adding the new OAuth2AuthProvider, and updating the agent loading mechanism to handle authentication for agent cards. A high-severity vulnerability was identified where OAuth2 client credentials could be leaked to an untrusted origin due to unvalidated endpoint discovery from remote agent cards; implementing origin validation for discovered OAuth2 endpoints is recommended. Additionally, the shared OAuth flow utility could benefit from more robust error handling.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/core/src/agents/auth-provider/oauth2-provider.ts (231-238)

security-high high

The OAuth2AuthProvider automatically discovers OAuth2 endpoints (authorizationUrl and tokenUrl) from the remote agent's card without validating that they belong to a trusted origin. If a user configures a remote agent with a client_secret but does not explicitly provide the endpoints in their local configuration, the CLI will discover them from the agent's card and send the client_secret to the discovered tokenUrl. A malicious or compromised agent could provide a tokenUrl pointing to an attacker-controlled server, leading to the theft of the user's OAuth2 client credentials.

Recommendation: Validate that discovered OAuth2 endpoints belong to the same origin as the agentCardUrl. If they differ, require the user to explicitly provide the endpoints in their local configuration or prompt for confirmation before sending sensitive credentials.

packages/core/src/utils/oauth-flow.ts (358-409)

high

The current token response parsing logic can be improved for robustness. If an OAuth server returns a 200 OK status with a JSON error payload (e.g., {"error":"invalid_grant"}), the current implementation will fall through to the form-urlencoded parser and produce a generic no_access_token error, obscuring the actual cause.

This suggestion refactors the parsing to:

  1. Handle JSON error objects correctly, even with a 200 OK status.
  2. Simplify the success-case JSON parsing.
  3. Ensure that specific errors from the server are propagated, which significantly aids in debugging authentication issues.
try {
  const data = JSON.parse(responseText) as Record<string, unknown>;
  if (typeof data?.access_token === 'string') {
    return {
      access_token: data.access_token,
      token_type: (data.token_type as string) || 'Bearer',
      expires_in: data.expires_in as number | undefined,
      refresh_token: data.refresh_token as string | undefined,
      scope: data.scope as string | undefined,
    };
  }
  if (typeof data?.error === 'string') {
    throw new Error(
      `${operationName} failed: ${data.error} - ${data.error_description || 'No description'}`,
    );
  }
} catch (e) {
  if (e instanceof Error && e.message.startsWith(operationName)) {
    throw e; // Rethrow our specific error
  }
  // Not valid JSON or not a recognized structure, fall through to form-urlencoded
}

// Parse form-urlencoded response
const tokenParams = new URLSearchParams(responseText);
const accessToken = tokenParams.get('access_token');
const tokenType = tokenParams.get('token_type') || 'Bearer';
const expiresIn = tokenParams.get('expires_in');
const refreshToken = tokenParams.get('refresh_token');
const scope = tokenParams.get('scope');

if (!accessToken) {
  // Check for error in response
  const error = tokenParams.get('error');
  const errorDescription = tokenParams.get('error_description');
  throw new Error(
    `${operationName} failed: ${error || defaultErrorCode} - ${errorDescription || responseText}`,
  );
}

return {
  access_token: accessToken,
  token_type: tokenType,
  expires_in: expiresIn ? parseInt(expiresIn, 10) : undefined,
  refresh_token: refreshToken || undefined,
  scope: scope || undefined,
};

@gemini-cli gemini-cli bot added the status/need-issue Pull requests that need to have an associated issue. label Mar 7, 2026
The OAuth2 auth provider's fetchAgentCardDefaults() was manually
parsing the raw agent card JSON, which only handled the JSON Schema
format. Proto-format agent cards (which use oneof field names instead
of a 'type' discriminator) were not recognized, causing authorization_url
and token_url discovery to silently fail.

Replace the manual parsing with DefaultAgentCardResolver, which
normalizes both JSON Schema and proto-format cards via the a2a-js SDK.
* OAuth2 auth schema.
* authorization_url and token_url can be discovered from the agent card if omitted.
*/
const oauth2AuthSchema = z.object({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this resilient to adding other types of oauth in the future. e.g. dynamic client registration. These interfaces are harder to change in the future as people will have them configured on their local.

…Replace eager 'agentCardRequiresAuth' with dynamic 401/403 retry wrapper for agent card fetching in A2AClientManager.\n- Remove 'requiresAgentAuth' and 'agentCardRequiresAuth' properties entirely from AgentRegistry, TOML parsing, and A2AClientManager.\n- Prevent token collisions by isolating A2A OAuth tokens from MCP tokens in OS Keychain via custom ServiceNames.
Copy link
Contributor

@adamfweidman adamfweidman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, waiting on a2aproject/a2a-js#344

@gemini-cli gemini-cli bot added area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. and removed status/need-issue Pull requests that need to have an associated issue. labels Mar 9, 2026
@adamfweidman adamfweidman enabled auto-merge March 10, 2026 14:54
@adamfweidman adamfweidman added this pull request to the merge queue Mar 10, 2026
Merged via the queue into main with commit b158c96 Mar 10, 2026
27 checks passed
@adamfweidman adamfweidman deleted the feat/oauth2-a2a-auth-provider branch March 10, 2026 15:36
JaisalJain pushed a commit to JaisalJain/gemini-cli that referenced this pull request Mar 11, 2026
kunal-10-cloud pushed a commit to kunal-10-cloud/gemini-cli that referenced this pull request Mar 12, 2026
liamhelmer pushed a commit to badal-io/gemini-cli that referenced this pull request Mar 12, 2026
DavidAPierce pushed a commit that referenced this pull request Mar 16, 2026
#21496)

Co-authored-by: Adam Weidman <adamfweidman@google.com>
yashodipmore pushed a commit to yashodipmore/geemi-cli that referenced this pull request Mar 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Remote Agents] OAuth 2.0: Authorization Code Flow

2 participants