Skip to content

Conversation

@cpunion
Copy link

@cpunion cpunion commented Dec 31, 2025

Base on:

#452 feat(auth): add OAuth2/OIDC authentication package

- Add AuthConfig, AuthCredential, AuthScheme types
- Add AuthHandler for OAuth2 flow orchestration
- Add CredentialManager and CredentialService for token management
- Add OAuth2 token exchange helpers
- Add unit tests for auth package
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @cpunion, 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 system's authentication capabilities by introducing a robust and extensible framework for managing various authentication types, with a strong focus on OAuth2 flows. It provides structured components for defining, handling, and persisting credentials, and seamlessly integrates these capabilities into the tool execution pipeline, allowing agents to dynamically request and utilize user authorization for API interactions.

Highlights

  • Comprehensive Authentication Framework: Introduced a new auth package with core components like AuthConfig, AuthCredential, AuthScheme, AuthHandler, CredentialManager, and CredentialService to standardize and manage various authentication types, including API Key, HTTP, OAuth2, and OpenID Connect.
  • OAuth2 Flow Orchestration: Added AuthHandler for generating OAuth authorization URIs and CredentialManager with pluggable OAuth2Exchanger and OAuth2Refresher for handling the full lifecycle of OAuth2 credentials, including exchange (e.g., auth code to access token) and token refreshing.
  • Persistent Credential Storage: Implemented CredentialService interface with InMemoryCredentialService and SessionStateCredentialService for loading and saving credentials, enabling persistence across requests.
  • Integration with OpenAPI Toolset: The RestApiTool within the openapitoolset now fully integrates with the new auth package, allowing OpenAPI-defined tools to manage and request user authorization for OAuth2 flows dynamically.
  • LLM Flow and Tool Context Enhancements: Modified the internal LLM flow (base_flow.go) to support 'Surgical Resumption' of tool execution after user authorization. The tool.Context interface was extended with RequestCredential, GetAuthResponse, and CredentialService methods to facilitate authentication interactions from within tools.
  • OAuth2 Example for GitHub API: Added a new example demonstrating how to use the openapitoolset with GitHub API, showcasing both OAuth2 Authorization Code and Device flows, and how the system handles requesting user credentials.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

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.

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 a comprehensive authentication framework, including support for various auth schemes like OAuth2, and integrates it with a new OpenAPI toolset. The implementation is extensive and well-structured, covering credential management, token exchange, and refresh logic. The new auth package is the core of this feature, and the openapitoolset provides a practical application of it. I've identified several areas for improvement, primarily concerning error handling and robustness. Specifically, there are cases where errors from JSON parsing and credential loading/refreshing are silently ignored, which could lead to unexpected behavior. Additionally, the example OAuth2 handler re-implements logic that is already available in the standard oauth2 library, making it more fragile. Addressing these points will significantly improve the reliability and maintainability of this new auth flow.

@cpunion cpunion force-pushed the feature/auth-flow branch 4 times, most recently from bc2af3e to 695a733 Compare January 1, 2026 04:11
@cpunion
Copy link
Author

cpunion commented Jan 1, 2026

/gemini review

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 a comprehensive authentication flow, primarily for OAuth2/OIDC, by adding a new auth package and integrating it into the existing agent and tool infrastructure. The changes are extensive, including new data structures for auth configurations and credentials, handlers for the auth lifecycle, and modifications to the core agent flow to support auth-related tool re-execution. While the overall structure is sound and aligns with the goals, I've identified several critical and high-severity issues related to error handling and security that need to be addressed. Specifically, there are cases of ignored errors in security-sensitive areas like random state generation and credential persistence, which could lead to vulnerabilities or runtime failures.

// generateRandomState generates a random state string for OAuth CSRF protection.
func generateRandomState() string {
b := make([]byte, 16)
rand.Read(b)
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The error from crypto/rand.Read is ignored. If reading from the OS's entropy source fails, the generated state for OAuth will not be random, which could compromise CSRF protection. This is a critical security risk. The error must be handled. Panicking would be appropriate here, as this indicates a critical failure in the environment.

if _, err := rand.Read(b); err != nil {
		// This is a critical failure. The OS's entropy source is not working.
		// Panicking is the only safe option.
		panic(fmt.Sprintf("failed to generate random state for OAuth: %v", err))
	}

if len(credentialService) > 0 && credentialService[0] != nil {
svc = credentialService[0]
if credential == nil {
loaded, _ := svc.LoadCredential(ctx, m.authConfig)
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The error returned from svc.LoadCredential is being ignored. If loading the credential from the service fails due to a transient issue, the error is silently swallowed. This could lead to unnecessary re-authentication flows. The error should be propagated and handled by the caller.

Suggested change
loaded, _ := svc.LoadCredential(ctx, m.authConfig)
loaded, err := svc.LoadCredential(ctx, m.authConfig)
if err != nil {
return nil, fmt.Errorf("failed to load credential from service: %w", err)
}

m.authConfig.ExchangedAuthCredential = credential
// Save to credential service for persistence across requests
if svc != nil {
svc.SaveCredential(ctx, m.authConfig)
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The error from svc.SaveCredential is ignored. If saving the credential fails, it won't be persisted for subsequent requests, potentially forcing the user to re-authenticate unnecessarily. This error should be handled, for example by returning it from GetAuthCredential.

if err := svc.SaveCredential(ctx, m.authConfig); err != nil {
				// Consider logging the error or propagating it.
			}

Comment on lines 214 to 233
refreshed, err := ref.Refresh(ctx, cred, m.authConfig.AuthScheme)
if err != nil {
// On refresh failure, return original
return cred, false
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The error returned by ref.Refresh is swallowed. If a token refresh fails, the original (likely expired) credential is returned without any indication of the failure. This can lead to subsequent API calls failing unexpectedly. The error should be propagated up to the caller of GetAuthCredential so it can be handled appropriately.

refreshed, err := ref.Refresh(ctx, cred, m.authConfig.AuthScheme)
	if err != nil {
		// On refresh failure, return an error instead of the original credential.
		return nil, fmt.Errorf("failed to refresh credential: %w", err)
	}

auth/helpers.go Outdated
Comment on lines 154 to 156
if err := json.Unmarshal(credentialJSON, &saCred); err == nil {
cred.ServiceAccount.ServiceAccountCredential = &saCred
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The error from json.Unmarshal is silently ignored. If the provided credentialJSON is invalid, this function will return a credential with a nil ServiceAccountCredential field without any indication of failure. This can lead to subtle bugs later on. The function should return an error to the caller to indicate that parsing failed.

if err := json.Unmarshal(credentialJSON, &saCred); err != nil {
			// Consider changing the function signature to return an error.
		} else {
			cred.ServiceAccount.ServiceAccountCredential = &saCred
		}

var schemePart string
if c.AuthScheme != nil {
schemeType := c.AuthScheme.GetType()
schemeJSON, _ := json.Marshal(c.AuthScheme)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The error returned by json.Marshal is being ignored. While marshalling this struct is unlikely to fail, it's a good practice to handle potential errors. A failure here could lead to silent issues like credential key collisions if schemeJSON is nil. Consider panicking if marshalling fails, as this would indicate a programming error (e.g., an unmarshallable type in the auth config).


var credPart string
if c.RawAuthCredential != nil {
credJSON, _ := json.Marshal(c.RawAuthCredential)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the AuthScheme marshalling, the error from json.Marshal for RawAuthCredential is ignored. This could lead to silent failures and key collisions. It's safer to handle this error, for instance by panicking, to prevent unexpected behavior.

Comment on lines +228 to +231
cred, err := parseAuthCredentialFromMap(credData)
if err == nil {
config.ExchangedAuthCredential = cred
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The error returned from parseAuthCredentialFromMap is ignored. If parsing the credential data fails, the error is silently swallowed, and config.ExchangedAuthCredential remains nil. This could cause the authentication flow to fail silently. The error should be handled, at least by logging it, to aid in debugging.

cred, err := parseAuthCredentialFromMap(credData)
		if err != nil {
			// Consider logging this error for debugging purposes.
			continue
		}
		config.ExchangedAuthCredential = cred

Add support for tools to request authentication credentials during execution:

- Add RequestedAuthConfigs field to EventActions for storing auth requests
- Implement GenerateAuthEvent to convert auth requests to adk_request_credential function calls
- Add RequestAuthConfig method to ToolContext for tools to request authentication
- Add AuthConfig field to Tool interface for tools to declare auth requirements
- Integrate auth event generation into the LLM base flow

Also fix test comparisons to ignore RequestedAuthConfigs field initialization
and add UTC timezone setup in database tests for consistent timestamp formatting.
@cpunion cpunion force-pushed the feature/auth-flow branch from 695a733 to 654e57b Compare January 1, 2026 05:16
@cpunion cpunion closed this Jan 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant