Agent-to-Agent (A2A) Authentication for NeMo Agent Toolkit#
NVIDIA NeMo Agent Toolkit provides OAuth2 authentication capabilities for A2A protocol, enabling secure agent-to-agent communication. A2A authentication is built on OAuth 2.1 Authorization Code Flow with JWT token validation, providing a standards-based approach to protecting A2A servers.
A2A authentication is agent card-driven; clients discover security requirements by fetching the agent’s public metadata (agent card) without authentication, then dynamically initiate the appropriate authentication flow. This allows agents to advertise their security requirements upfront, enabling clients to adapt their authentication strategy accordingly.
For a complete, hands-on guide to setting up OAuth2 authentication with Keycloak, see examples/A2A/math_assistant_a2a_protected/README.md.
Supported Capabilities#
NeMo Agent toolkit A2A authentication provides the capabilities required for secure agent-to-agent communication:
Agent Card Discovery: Public endpoint for discovering security requirements without authentication
OAuth 2.1 Authorization Code Flow: Standard authorization flow conforming to OAuth 2.1 draft specification
JWT Token Validation: Server-side token verification using JWKS (JSON Web Key Set)
Custom Scopes: Resource-specific permissions (for example,
calculator_a2a_execute)Audience Validation: Ensures tokens are intended for the specific A2A server
Architecture Overview#
A2A authentication involves three main components working together to secure agent-to-agent communication:
(Math Assistant)"] A2AClientPlugin["A2A Client Plugin
• Discovers agent card
• Handles OAuth2 flow
• Manages JWT tokens"] ClientWorkflow --> A2AClientPlugin end subgraph Server["A2A Server (Resource Server)"] direction TB ServerWorkflow["Workflow
(Calculator)"] OAuthMiddleware["OAuth Middleware
• Validates JWT tokens
• Checks scopes & audience
• Caches JWKS"] ServerWorkflow --> OAuthMiddleware end subgraph Auth["Authorization Server"] direction LR AuthCore["OAuth2 Server
(Keycloak, Auth0, etc.)
• Authenticates users
• Issues JWT tokens
• Provides JWKS endpoint"] end A2AClientPlugin -->|"① GET /.well-known/agent-card.json
(Public - No Auth)"| ServerWorkflow A2AClientPlugin -->|"② OAuth2 Authorization Flow
(Browser-based)"| AuthCore A2AClientPlugin -->|"③ A2A JSON-RPC Requests
(Authorization: Bearer JWT)"| ServerWorkflow OAuthMiddleware -.->|"Verify JWT
(Fetch JWKS)"| AuthCore style Client fill:#e1f5ff style Server fill:#ffe1e1 style Auth fill:#e1ffe1
Component Roles:
A2A Client: workflow that connects to remote A2A agents using the
a2a_clientfunction group. Handles OAuth2 flow and includes JWT tokens in requests.A2A Server (Resource Server): workflow published via
nat a2a servewith OAuth2 protection. Validates incoming JWT tokens and enforces access policies.Authorization Server: OAuth2 server (such as Keycloak) that authenticates users, issues JWT tokens, and provides public keys for token verification.
Authentication Flow#
The A2A authentication flow demonstrates how agent card discovery drives the authentication process:
(Math Assistant) participant Browser as User Browser participant AuthServer as Authorization Server
(OAuth2) participant Server as Remote A2A Agent
(Calculator) Note over Client,Server: 1. Discovery Phase (Public - No Auth) Client->>Server: GET /.well-known/agent-card.json Server-->>Client: Agent card with security schemes
{security: [{oauth2: [...]}], securitySchemes: {...}} Client->>Client: Parse security requirements
Discover OAuth2 endpoints Note over Client,AuthServer: 2. Authorization Phase (If Required) Client->>Browser: Open authorization URL Browser->>AuthServer: GET authorization_endpoint
(client_id, redirect_uri, scope) AuthServer->>Browser: Login page Browser->>AuthServer: User credentials AuthServer->>Browser: Consent page
(Request scopes) Browser->>AuthServer: User approves Note over Client,AuthServer: 3. Token Exchange AuthServer->>Browser: Redirect with authorization code Browser->>Client: Authorization code Client->>AuthServer: POST token_endpoint
(code, client_secret) AuthServer-->>Client: Access token (JWT)
{scope: ..., aud: ..., exp: ...} Note over Client,Server: 4. Authenticated Communication Client->>Server: POST / (JSON-RPC)
Authorization: Bearer
Validate issuer, audience, scopes, expiration Server-->>Client: A2A response
Key Steps:
Agent Card Discovery: Client fetches public metadata to discover authentication requirements. This step requires no authentication and is always the first interaction.
Dynamic Authentication: Client initiates OAuth2 flow based on agent card security schemes. The agent card specifies the authorization server, token endpoint, and required scopes.
Token Acquisition: User authenticates via browser, and client obtains JWT access token with appropriate scopes and audience.
Authenticated Communication: Client includes JWT token in A2A requests. Server validates token signature, issuer, audience, scopes, and expiration before processing requests.
Configuring Authentication#
A2A authentication requires configuration on both the client side (OAuth2 provider) and server side (JWT validation).
Client Configuration (A2A Client with OAuth2)#
Configure the A2A client to use an OAuth2 authentication provider:
function_groups:
calculator_a2a:
_type: a2a_client
url: http://localhost:10000
auth_provider: calculator_oauth
authentication:
calculator_oauth:
_type: oauth2_auth_code_flow
client_id: ${CALCULATOR_CLIENT_ID}
client_secret: ${CALCULATOR_CLIENT_SECRET}
redirect_uri: http://localhost:8000/auth/redirect
authorization_url: http://localhost:8080/realms/master/protocol/openid-connect/auth
token_url: http://localhost:8080/realms/master/protocol/openid-connect/token
scopes:
- calculator_a2a_execute
Configuration Options:
Parameter |
Description |
Required |
|---|---|---|
|
OAuth2 client identifier registered with authorization server |
Yes |
|
OAuth2 client secret |
Yes |
|
Callback URI for OAuth2 flow (must match registration) |
Yes |
|
Authorization endpoint URL |
Yes |
|
Token endpoint URL |
Yes |
|
List of OAuth2 scopes to request |
Yes |
Endpoint Discovery: The authorization_url and token_url can be discovered from your OAuth2 provider’s discovery endpoint (typically /.well-known/openid-configuration). For example, Keycloak uses paths like /protocol/openid-connect/auth and /protocol/openid-connect/token.
Note: Get the complete list of OAuth2 provider options by running:
nat info components -t auth_provider -q oauth2_auth_code_flow
Server Configuration (A2A Server with JWT Validation)#
Configure the A2A server to validate JWT tokens:
general:
front_end:
_type: a2a
name: "Protected Calculator"
description: "OAuth2-protected calculator agent"
port: 10000
server_auth:
issuer_url: http://localhost:8080/realms/master
scopes:
- calculator_a2a_execute
audience: http://localhost:10000
jwks_uri: http://localhost:8080/realms/master/protocol/openid-connect/certs
Server Authentication Options:
Parameter |
Description |
Required |
|---|---|---|
|
Expected token issuer (authorization server URL) |
Yes |
|
JWKS endpoint for fetching public keys |
Yes |
|
Required scopes for access |
Optional |
|
Expected audience value in token |
Optional |
Endpoint Discovery: The jwks_uri can be discovered from your OAuth2 provider’s discovery endpoint at <issuer_url>/.well-known/openid-configuration. For example, Keycloak typically uses /protocol/openid-connect/certs.
The server validates incoming JWT tokens by:
Verifying token signature using public keys from JWKS endpoint
Checking token issuer matches
issuer_urlValidating token has not expired
Ensuring required scopes are present (if configured)
Verifying audience matches expected value (if configured)
Security Considerations#
When implementing A2A authentication, consider the following security best practices:
Transport Security#
Always use HTTPS in production for all components (authorization server, A2A server, redirect URIs)
Secure redirect URIs: Ensure redirect URIs use HTTPS and match registered URIs exactly
No HTTP in production: HTTP is acceptable only for local development
Token Management#
Short-lived tokens: Configure access tokens with short lifetimes (5-15 minutes recommended)
Scope minimization: Request only the scopes required for specific operations
Audience validation: Always validate the token audience to prevent token substitution attacks
Credential Security#
Secure client secrets: Store client secrets in environment variables or secret management systems
Never commit secrets: Do not commit OAuth2 credentials to version control
Rotate credentials: Implement regular credential rotation policies
Examples#
The Math Assistant A2A example demonstrates end-to-end OAuth2-protected A2A communication:
Protected Calculator Server: A2A server that validates JWT tokens and enforces scope requirements
Math Assistant Client: A2A client that discovers security requirements and authenticates via OAuth2
OAuth2 Keycloak Setup Guide: Complete guide for setting up Keycloak as authorization server
Example Location: examples/A2A/math_assistant_a2a_protected/
This example includes:
Complete Keycloak configuration instructions
Client and server configuration files
Testing and verification steps