Skip to content

Conversation

@jezekra1
Copy link
Collaborator

@jezekra1 jezekra1 commented Dec 19, 2025

Summary

Important changes:

  • a2a clients can now use platform context token in the authorization header instead of sending 2 tokens - user OIDC token in the header and context token in the platform api extension fullfilment
  • platform api extension fullfilment body is now optional, if a token is provided in the header and is a context token, it will be used
  • a2a proxy on the server does "token exchange" -> if it receives a context token it creates a new context token with the same claims and expiration, but targeted "audience" in aud claim.
    • This is passed to the SDK using the PLATFORM_AUTH__PUBLIC_URL env for managed providers and validated.
    • This ensures that agents secured by platform authentication cannot use the token to call other agents directly, they must always go through the platform proxy.
    • This is important because direct access be a security hole where it's possible to exfiltrate data of other users using task/list or task/get methods from a2a, which are not properly scoped per user. The a2a proxy is tracking task ownership and won't allow these methods if unauthorized.
  • All changes should be backwards compatible

Todos:

  • test backwards compatibility
  • test managed agents
  • add sdk tests
  • improve frontend implementation

Linked Issues

Ref: #1637

Documentation

  • No Docs Needed:

If this PR adds new feature or changes existing. Make sure documentation is adjusted accordingly. If the docs is not needed, please explain why.

@jezekra1 jezekra1 changed the title Platform auth wip Add authorization to agents using cotext token Dec 19, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jezekra1, 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 overhauls the platform's authentication infrastructure, moving to a more secure RSA-based JWT system. It ensures that agent interactions are properly authenticated and authorized by integrating a new authentication backend, refining how tokens are managed and exchanged between services, and updating both the core SDK and user interface to support these changes. The update also includes general improvements to dependency handling and type consistency across the codebase.

Highlights

  • Platform Authentication Refactor: The pull request introduces a robust platform authentication mechanism, transitioning JWT handling from symmetric HS256 with a shared secret key to asymmetric RS256 with private/public key pairs for enhanced security. This includes new middleware for FastAPI applications and updated token exchange logic.
  • Dependency Management and Type System Enhancements: New dependencies async-lru and authlib are integrated across Python projects. The SDK's dependency injection system is refined to incorporate RequestContext, and type definitions for JSON values (JsonValue, JsonDict) are centralized for consistency.
  • Agent Server and Client Updates: The agent server now integrates a PlatformAuthBackend and handles RequestContext more explicitly in its lifecycle and dependency resolution. The A2A client is updated to manage and pass authentication tokens for secure communication with agents, including granular permission checks for a2a_proxy.
  • UI and Helm Chart Adjustments: The UI components are updated to support the new authentication flow, including generating and utilizing context tokens. Helm charts are modified to reflect the new JWT private and public key configurations, ensuring proper deployment of the secure authentication system.
  • Codebase Cleanup and Standardization: Outdated monkey-patching for extension specifications is removed, and various type hints are updated across the codebase for improved clarity and maintainability. New endpoints like /jwks are exposed for public key discovery.

🧠 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 significant and wide-ranging feature to add authorization to agents using context tokens. The changes span across the Python SDK, CLI, server, and the TypeScript UI, as well as configuration files and Helm charts. Key changes include the introduction of a PlatformAuthBackend for JWT-based authentication, a switch from symmetric (HS256) to asymmetric (RS256) JWT signing, and a substantial refactoring of how agent extensions handle request context and authentication. The overall approach is solid and well-implemented. However, I've identified a critical bug in the UI related to context token handling, a potential issue with query caching in React, and a configuration change in the Python SDK that could hide future bugs. Addressing these points will improve the robustness of this new authentication system.

Comment on lines 56 to 59
export async function createContextToken(createContextTokenParams: CreateContextTokenParams) {
console.log(createContextTokenParams)
const result = await agentstackClient.createContextToken(createContextTokenParams);
return result.token;
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

This function has two issues:

  1. A console.log statement is present, which appears to be for debugging and should be removed.
  2. The function returns result.token (a string), but the caller in AgentRunProvider.tsx expects the full ContextToken object ({ token: string, expires_at: string }). This will cause a runtime error or incorrect behavior. The function should return the entire result object.
export async function createContextToken(createContextTokenParams: CreateContextTokenParams) {
  const result = await agentstackClient.createContextToken(createContextTokenParams);
  return result;
}

}: Props<UIGenericPart>) {
const { data: agentClient } = useQuery({
queryKey: runKeys.client(providerId),
queryKey: runKeys.client(`${providerId}${Boolean(authToken)}`),
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 queryKey for useBuildA2AClient includes Boolean(authToken). This is insufficient to detect changes in the authentication token. If the token is refreshed, Boolean(authToken) will remain true, and the query will not be re-triggered, causing the old agentClient with a stale token to be used. The query key should incorporate the token value itself to ensure the client is rebuilt when the token changes.

Suggested change
queryKey: runKeys.client(`${providerId}${Boolean(authToken)}`),
queryKey: runKeys.client(`${providerId}${authToken?.token}`),

ignore = ["tests/**", "examples/cli.py"]
venvPath = "."
venv = ".venv"
reportUnusedCallResult = "none"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Disabling reportUnusedCallResult globally can be risky. While it cleans up the need for _ = ... for functions where the return value is intentionally ignored, it also silences warnings for forgotten await statements on coroutines. This can lead to subtle and hard-to-debug concurrency issues. A safer approach is to keep this check enabled and explicitly ignore unused results where necessary (e.g., by assigning to _).

token, _ = exchange_internal_jwt(header_token, self._configuration, audience=[audience])
headers["authorization"] = f"Bearer {token}"
except Exception:
headers.pop("authorization", None) # forward header only if it's a valid context token
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Forwarding the request without the Authorization header when the token exchange fails is a reasonable fallback. However, it might be beneficial to log a warning in this except block. This would make it easier to debug situations where agent calls are unexpectedly unauthenticated because the context token exchange failed for some reason.

Signed-off-by: Radek Ježek <[email protected]>
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.

2 participants