chore: import upstream snapshot with attribution
Continuous Integration / Pre-commit Linter (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.10) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.11) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.12) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.12) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.14) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Has been cancelled
Copybara PR Handler / close-imported-pr (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Has been cancelled
Continuous Integration / Pre-commit Linter (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.10) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.11) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.12) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.12) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.14) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Has been cancelled
Copybara PR Handler / close-imported-pr (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# GitHub OAuth Authentication Sample
|
||||
|
||||
## Overview
|
||||
|
||||
This sample demonstrates how to use `AuthConfig` with GitHub OAuth2 on a `FunctionNode` in a workflow. It shows how to pause execution to request a GitHub OAuth token from the user and then use that token to list the user's owned repositories via the GitHub API.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To run this sample and actually log in, you need to:
|
||||
|
||||
1. **Register an OAuth Application on GitHub**:
|
||||
- Go to your GitHub account settings.
|
||||
- Navigate to **Developer settings** > **OAuth Apps** > **New OAuth App**.
|
||||
- Set the **Homepage URL** and **Authorization callback URL** appropriate for your testing environment (e.g., `http://localhost:8000` if running locally).
|
||||
1. **Get Credentials**:
|
||||
- Copy the **Client ID** and **Client Secret**.
|
||||
1. **Configure Environment Variables**:
|
||||
- Set the following environment variables in your terminal before running the sample:
|
||||
```bash
|
||||
export GITHUB_CLIENT_ID="your_actual_client_id"
|
||||
export GITHUB_CLIENT_SECRET="your_actual_client_secret"
|
||||
```
|
||||
- Alternatively, you can create a `.env` file in the sample directory (`contributing/workflow_samples/auth_oauth/.env`) with the following content:
|
||||
```env
|
||||
GITHUB_CLIENT_ID="your_actual_client_id"
|
||||
GITHUB_CLIENT_SECRET="your_actual_client_secret"
|
||||
```
|
||||
The ADK CLI automatically loads `.env` files from the agent directory.
|
||||
|
||||
## Sample Inputs
|
||||
|
||||
- `start`
|
||||
|
||||
- `list my repos`
|
||||
|
||||
## Graph
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
START --> list_github_repos
|
||||
list_github_repos --> display_result
|
||||
```
|
||||
|
||||
## How To
|
||||
|
||||
### 1. Define the AuthConfig for GitHub
|
||||
|
||||
We define an `AuthConfig` that specifies the GitHub OAuth2 endpoints and reads credentials from environment variables.
|
||||
|
||||
```python
|
||||
auth_config = AuthConfig(
|
||||
auth_scheme=OAuth2(
|
||||
flows=OAuthFlows(
|
||||
authorizationCode=OAuthFlowAuthorizationCode(
|
||||
authorizationUrl="https://github.com/login/oauth/authorize",
|
||||
tokenUrl="https://github.com/login/oauth/access_token",
|
||||
scopes={
|
||||
"user": "Read user profile",
|
||||
"repo": "Access public repositories",
|
||||
},
|
||||
)
|
||||
)
|
||||
),
|
||||
raw_auth_credential=AuthCredential(
|
||||
auth_type=AuthCredentialTypes.OAUTH2,
|
||||
oauth2=OAuth2Auth(
|
||||
client_id=os.environ.get("GITHUB_CLIENT_ID", "YOUR_GITHUB_CLIENT_ID"),
|
||||
client_secret=os.environ.get("GITHUB_CLIENT_SECRET", "YOUR_GITHUB_CLIENT_SECRET"),
|
||||
),
|
||||
),
|
||||
credential_key="github_oauth_token",
|
||||
)
|
||||
```
|
||||
|
||||
### 2. Apply to a Node
|
||||
|
||||
We apply the `auth_config` to the `list_github_repos` node.
|
||||
|
||||
```python
|
||||
@node(auth_config=auth_config, rerun_on_resume=True)
|
||||
def list_github_repos(ctx: Context):
|
||||
# ...
|
||||
```
|
||||
|
||||
### 3. Call GitHub API
|
||||
|
||||
Inside the node, we retrieve the token and use the `requests` library to call the GitHub API.
|
||||
|
||||
```python
|
||||
cred = ctx.get_auth_response(auth_config)
|
||||
access_token = cred.oauth2.access_token if cred and cred.oauth2 else None
|
||||
|
||||
# ... (headers setup) ...
|
||||
|
||||
response = requests.get("https://api.github.com/user/repos", headers=headers)
|
||||
repos_data = response.json()
|
||||
repo_names = [repo["name"] for repo in repos_data]
|
||||
```
|
||||
|
||||
## Running the Sample
|
||||
|
||||
To run this sample interactively, use the ADK CLI:
|
||||
|
||||
```bash
|
||||
adk run contributing/workflow_samples/auth_oauth
|
||||
```
|
||||
|
||||
Or use the Web UI:
|
||||
|
||||
```bash
|
||||
adk web contributing/workflow_samples/
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright 2026 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from . import agent
|
||||
@@ -0,0 +1,135 @@
|
||||
# Copyright 2026 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""OAuth Authentication sample: FunctionNode with GitHub OAuth2 token request.
|
||||
|
||||
Demonstrates how to use `auth_config` with GitHub OAuth2 on a FunctionNode to pause
|
||||
the workflow, request an OAuth token from the user, and use it to list the user's
|
||||
GitHub repositories.
|
||||
|
||||
Flow:
|
||||
1. User sends any message to start the workflow.
|
||||
2. The `list_github_repos` node pauses and requests GitHub OAuth credentials.
|
||||
3. The user provides the credentials (after logging in to GitHub).
|
||||
4. The node runs, calls the GitHub API to list repos, and returns the list.
|
||||
5. The `display_result` node displays the repository names.
|
||||
|
||||
Sample queries:
|
||||
- "start"
|
||||
- "list my repos"
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from fastapi.openapi.models import OAuth2
|
||||
from fastapi.openapi.models import OAuthFlowAuthorizationCode
|
||||
from fastapi.openapi.models import OAuthFlows
|
||||
from google.adk import Event
|
||||
from google.adk import Workflow
|
||||
from google.adk.agents.context import Context
|
||||
from google.adk.auth.auth_credential import AuthCredential
|
||||
from google.adk.auth.auth_credential import AuthCredentialTypes
|
||||
from google.adk.auth.auth_credential import OAuth2Auth
|
||||
from google.adk.auth.auth_tool import AuthConfig
|
||||
from google.adk.workflow import node
|
||||
import requests
|
||||
|
||||
# --- Auth configuration ---
|
||||
# Uses GitHub OAuth2 authorization code flow.
|
||||
# To use this sample, you need to register an OAuth application on GitHub
|
||||
# and get a Client ID and Client Secret.
|
||||
# Set the GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET environment variables.
|
||||
auth_config = AuthConfig(
|
||||
auth_scheme=OAuth2(
|
||||
flows=OAuthFlows(
|
||||
authorizationCode=OAuthFlowAuthorizationCode(
|
||||
authorizationUrl="https://github.com/login/oauth/authorize",
|
||||
tokenUrl="https://github.com/login/oauth/access_token",
|
||||
scopes={
|
||||
"user": "Read user profile",
|
||||
"repo": "Access public repositories",
|
||||
},
|
||||
)
|
||||
)
|
||||
),
|
||||
raw_auth_credential=AuthCredential(
|
||||
auth_type=AuthCredentialTypes.OAUTH2,
|
||||
oauth2=OAuth2Auth(
|
||||
client_id=os.environ.get(
|
||||
"GITHUB_CLIENT_ID", "YOUR_GITHUB_CLIENT_ID"
|
||||
),
|
||||
client_secret=os.environ.get(
|
||||
"GITHUB_CLIENT_SECRET", "YOUR_GITHUB_CLIENT_SECRET"
|
||||
),
|
||||
),
|
||||
),
|
||||
credential_key="github_oauth_token",
|
||||
)
|
||||
|
||||
|
||||
@node(auth_config=auth_config, rerun_on_resume=True)
|
||||
def list_github_repos(ctx: Context):
|
||||
"""Fetches GitHub repositories for the authenticated user."""
|
||||
# After auth completes, the credential is available via ctx.
|
||||
cred = ctx.get_auth_response(auth_config)
|
||||
|
||||
access_token = cred.oauth2.access_token if cred and cred.oauth2 else None
|
||||
|
||||
if not access_token:
|
||||
return {"status": "Error", "message": "No access token found"}
|
||||
|
||||
# GitHub API requires a User-Agent header
|
||||
headers = {
|
||||
"Authorization": f"Bearer {access_token}",
|
||||
"User-Agent": "ADK-Sample-Agent",
|
||||
"Accept": "application/json",
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(
|
||||
"https://api.github.com/user/repos", headers=headers
|
||||
)
|
||||
response.raise_for_status()
|
||||
repos_data = response.json()
|
||||
# Extract repo names
|
||||
repo_names = [repo["name"] for repo in repos_data]
|
||||
return {
|
||||
"status": "Success",
|
||||
"repos": repo_names,
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": "Error",
|
||||
"message": f"Failed to fetch repos: {e}",
|
||||
}
|
||||
|
||||
|
||||
def display_result(node_input: dict):
|
||||
"""Displays the result of accessing the resource."""
|
||||
if node_input["status"] == "Success":
|
||||
repos_str = ", ".join(node_input["repos"])
|
||||
yield Event(message=f"Successfully fetched repositories: {repos_str}")
|
||||
else:
|
||||
yield Event(
|
||||
message=(
|
||||
"Failed to fetch repositories. Error:"
|
||||
f" {node_input.get('message', 'Unknown error')}"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
root_agent = Workflow(
|
||||
name="auth_oauth",
|
||||
edges=[("START", list_github_repos, display_result)],
|
||||
)
|
||||
Reference in New Issue
Block a user