Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 67 additions & 11 deletions docs/tools-custom/authentication.md

@zyantw zyantw Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

i didn't put the link in brackets to avoid errors in the automated link-checker, is this ok or is there a better solution? @joefernandez
Thanks for your review!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The lychee link checker will check all URLs in a .md source file, either URLs within link brackets or just raw URLs.

However, the default lychee setting for --include-verbatim is false, which means that lychee will not check URLs within in-line code blocks or fenced code blocks. So the convention you can use here is to wrap your sample URL (that should not be checked) in an in-line code block, as in:

The URL of the service you are calling, for example, `https://my-service.run.app`.

And that should make the link checker skip it and the CI check should pass once you do that.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Awesome @koverholt! Thanks for the tip. I worked in all of @joefernandez comments. Let me know if I can merge it.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Authenticating with Tools
# Authenticating with tools

<div class="language-support-tag">
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v0.1.0</span>
Expand Down Expand Up @@ -157,15 +157,15 @@ see the [ADK Integrations](/integrations) catalog.

---

## Journey 1: Building Agentic Applications with Authenticated Tools
## Build Agentic Applications with Authenticated Tools

This section focuses on using pre-existing tools (like those from `RestApiTool/ OpenAPIToolset`, `APIHubToolset`, `GoogleApiToolSet`) that require authentication within your agentic application. Your main responsibility is configuring the tools and handling the client-side part of interactive authentication flows (if required by the tool).

### 1. Configuring Tools with Authentication
### Configure Tools with Authentication

When adding an authenticated tool to your agent, you need to provide its required `AuthScheme` and your application's initial `AuthCredential`.

**A. Using OpenAPI-based Toolsets (`OpenAPIToolset`, `APIHubToolset`, etc.)**
#### A. Use OpenAPI-based Toolsets (`OpenAPIToolset`, `APIHubToolset`, etc.)

Pass the scheme and credential during toolset initialization. The toolset applies them to all generated tools. Here are few ways to create tools with authentication in ADK.

Expand Down Expand Up @@ -279,7 +279,7 @@ Pass the scheme and credential during toolset initialization. The toolset applie
)
```

**B. Using Google API Toolsets (e.g., `calendar_tool_set`)**
#### B. Use Google API Toolsets (e.g., `calendar_tool_set`)

These toolsets often have dedicated configuration methods.

Expand All @@ -300,17 +300,73 @@ calendar_tool_set.configure_auth(
# agent = LlmAgent(..., tools=calendar_tool_set.get_tool('calendar_tool_set'))
```

The sequence diagram of auth request flow (where tools are requesting auth credentials) looks like below:
#### C. Use ID Token

If your agent calls a restricted service, for example a private Cloud Run or Cloud Function, the agent needs to prove your identity, not just your permissions. If you are calling a service that is accessed using Cloud IAM, you should use an ID token.

* **Access Token (Default)**: It calls Google APIs (Drive, BigQuery). Think of it as your keycard.

* **ID Token**: It calls your own services secured by IAM. Think of it as your passport.

##### Configuration
Comment thread
zyantw marked this conversation as resolved.

To implement ID Token authentication, configure your ServiceAccount with the following parameters, ensuring you specify the target service's URL as the `audience`.

```python
from google.adk.auth.auth_credential import ServiceAccount

# Configure the ServiceAccount to use ID Token authentication.
# Replace <YOUR_AUDIENCE_URL> with the URL of the service you are calling.
sa_config = ServiceAccount(
use_default_credential=True,
use_id_token=True,
audience="<YOUR_AUDIENCE_URL>"
)

```

!!! Tip
If you receive an authentication error, verify that your service account has the 'Cloud Run Invoker' or equivalent role on the target service.

##### Key takeaways

* **Audience Requirement**: The `audience` is a security feature. It binds the token to a specific destination so it cannot be "replayed" against other services.

* **No Auto-Refresh**: Unlike standard OAuth2 access tokens for users, service-account ID tokens are fetched at the time of the request. They do not auto-refresh on a background timer.

* **The Flow**: You define the intent and ADK handles the handshake, fetches the token from Google's auth servers, and injects it into your outgoing HTTP headers.

##### ServiceAccount configuration parameters

Configure your `ServiceAccount` to use ID token authentication and specify the target service's URL as the `audience`.

* `service_account_credential` (Optional): Provide the path or dict for your service account JSON key file. Use this if you are running locally or outside of Google Cloud.

* ` use_default_credential` (Optional): Set to True to use Application Default Credentials (ADC). Recommended if your agent is already running within Google Cloud, for example on Cloud Run or Cloud Functions, as it avoids the need for local key files.

* `use_id_token` (Required for IAM): Set to True to enable ID token-based authentication. This switches the ADK from requesting an Access Token, for Google APIs, to an ID Token, for your own IAM-secured services.

* `audience` (Required if use_id_token=True): The URL of the service you are calling, for example, `https://my-service.run.app`. This is a security binding that ensures the token is valid only for that specific destination.

* `scopes` (Optional): Use it only when requesting Access Tokens for Google Cloud APIs, like Drive or BigQuery. You do not need to set this if you are using ID tokens for private service authentication.

!!! tip
Always use `use_id_token=True` and `audience` together. If you provide one without the other, the ADK will raise an error to prevent accidental misconfiguration.

#### Authentication request flow

This diagram visualizes the end-to-end authentication handshake, tracing the path from the initial user query to the point where the ADK captures a credential request,
handles the redirection flow, and retries the tool call once authorized.

![Authentication](../assets/auth_part1.svg)


### 2. Handling the Interactive OAuth/OIDC Flow (Client-Side)
### Handle the Interactive OAuth/OIDC Flow (Client-Side)

If a tool requires user login/consent (typically OAuth 2.0 or OIDC), the ADK framework pauses execution and signals your ***Agent Client*** application. There are two cases:

* ***Agent Client*** application runs the agent directly (via `runner.run_async`) in the same process. e.g. UI backend, CLI app, or Spark job etc.
* ***Agent Client*** application interacts with ADK's fastapi server via `/run` or `/run_sse` endpoint. While ADK's fastapi server could be setup on the same server or different server as ***Agent Client*** application
* **Agent Client** application runs the agent directly (via `runner.run_async`) in the same process. e.g. UI backend, CLI app, or Spark job etc.
* **Agent Client** application interacts with ADK's fastapi server via `/run` or `/run_sse` endpoint. While ADK's fastapi server could be setup on the same server or different server as ***Agent Client*** application

The second case is a special case of first case, because `/run` or `/run_sse` endpoint also invokes `runner.run_async`. The only differences are:

Expand All @@ -327,7 +383,7 @@ Here's the step-by-step process for your client application:
* Iterate through the yielded events.
* Look for a specific function call event whose function call has a special name: `adk_request_credential`. This event signals that user interaction is needed. You can use helper functions to identify this event and extract necessary information. (For the second case, the logic is similar. You deserialize the event from the http response).

```py
```python

# runner = Runner(...)
# session = await session_service.create_session(...)
Expand Down Expand Up @@ -511,7 +567,7 @@ The sequence diagram of auth response flow, where the ***Agent Client*** sends b

![Authentication](../assets/auth_part2.svg)

## Journey 2: Building Custom Tools (`FunctionTool`) Requiring Authentication
## Build custom tools (`FunctionTool`) requiring authentication

This section focuses on implementing the authentication logic *inside* your custom Python function when creating a new ADK Tool. We will implement a `FunctionTool` as an example.

Expand Down
Loading