使用三足式 OAuth 和驗證管理員進行驗證

如要代表特定使用者授予代理外部工具和服務 (例如 Jira 工作或 GitHub 存放區) 的存取權,請在代理身分驗證管理員中設定三足式 OAuth 驗證提供者。

三足式 OAuth 驗證供應商可管理憑證和權杖,因此您不需要自訂程式碼來處理驗證流程。

三足式 OAuth 工作流程

三足式 OAuth 驗證提供者需要使用者同意,因為代理程式會代表使用者存取資源。

  1. 提示和重新導向:聊天介面會提示使用者登入,然後將使用者重新導向至第三方應用程式的同意頁面。
  2. 同意聲明和儲存:使用者授予權限後,Agent Identity 驗證管理工具會將產生的 OAuth 權杖儲存在 Google 管理的憑證保管庫中。
  3. 注入:使用 Agent Development Kit (ADK) 時,代理會自動從驗證供應商擷取權杖,並將權杖注入工具叫用標頭。

事前準備

  1. 確認您選擇的驗證方法正確無誤
  2. 啟用 Agent Identity API。

    啟用 API 時所需的角色

    如要啟用 API,您需要具備服務使用情形管理員 IAM 角色 (roles/serviceusage.serviceUsageAdmin),其中包含 serviceusage.services.enable 權限。瞭解如何授予角色

    啟用 API

  3. 建立及部署代理程式
  4. 請確認您有前端應用程式,可處理使用者登入提示,並將使用者重新導向至第三方同意聲明頁面。
  5. 確認您具備完成這項工作所需的角色

必要的角色

如要取得建立及使用三方授權供應商所需的權限,請要求管理員授予您專案的下列 IAM 角色:

如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。

這些預先定義的角色具備建立及使用三足式授權供應商所需的權限。如要查看確切的必要權限,請展開「Required permissions」(必要權限) 部分:

所需權限

如要建立及使用三足式驗證供應商,必須具備下列權限:

  • 如要建立驗證提供者: agentidentity.authProviders.create
  • 如何使用驗證提供者:
    • agentidentity.authProviders.retrieveCredentials
    • aiplatform.endpoints.predict
    • aiplatform.sessions.create

您或許還可透過自訂角色或其他預先定義的角色取得這些權限。

建立 3 向驗證供應程式

建立驗證提供者,定義第三方應用程式的設定和憑證。

如要建立 3-legged 驗證供應商,請使用 gcloud CLI:

  1. 設定 OAuth 用戶端應用程式,註冊用戶端並取得用戶端 ID 和用戶端密鑰。使用該節中的範本指定重新導向 URI。

  2. 使用用戶端憑證建立驗證供應商:

    gcloud alpha agent-identity authProviders create AUTH_PROVIDER_NAME \
        --project="PROJECT_ID" \
        --location="LOCATION" \
        --three-legged-oauth-client-id="CLIENT_ID" \
        --three-legged-oauth-client-secret="CLIENT_SECRET" \
        --three-legged-oauth-authorization-url="AUTHORIZATION_URL" \
        --three-legged-oauth-token-url="TOKEN_URL"
  3. 確認驗證供應商顯示在清單中,且狀態為 ENABLED
    gcloud alpha agent-identity authProviders list \
       --project="PROJECT_ID" \
       --location="LOCATION"
  4. 授予存取權,允許代理程式和本機開發環境從驗證提供者擷取憑證。如要允許已部署的代理程式和個人使用者帳戶存取驗證供應商,請在驗證供應商資源上授予「Agent Identity User」(代理程式身分使用者) (roles/agentidentity.user) 角色:

    1. 授予已部署代理的 SPIFFE ID (代理身分) 存取權:

      gcloud alpha agent-identity authProviders add-iam-policy-binding AUTH_PROVIDER_NAME \
          --project="PROJECT_ID" \
          --location="LOCATION" \
          --role="roles/agentidentity.user" \
          --member="principal://agents.global.org-ORGANIZATION_ID.system.id.goog/resources/aiplatform/projects/PROJECT_NUMBER/locations/LOCATION/reasoningEngines/ENGINE_ID"
    2. 授予個人使用者帳戶存取權,以進行本機開發和測試 (adk web):

      gcloud alpha agent-identity authProviders add-iam-policy-binding AUTH_PROVIDER_NAME \
          --project="PROJECT_ID" \
          --location="LOCATION" \
          --role="roles/agentidentity.user" \
          --member="user:USER_EMAIL"

更改下列內容:

  • PROJECT_ID: Google Cloud 專案 ID。
  • LOCATION:部署驗證供應商和代理程式的位置 (例如 us-west1)。
  • AUTH_PROVIDER_NAME:驗證供應商的名稱 (例如 bigquery-mcp-3lo-authprovider)。
  • AUTHORIZATION_URL:授權伺服器網址 (例如 https://accounts.google.com/o/oauth2/v2/auth)。
  • TOKEN_URL:權杖伺服器網址 (例如 https://oauth2.googleapis.com/token)。
  • CLIENT_ID:您從第三方服務產生的 OAuth 用戶端 ID。
  • CLIENT_SECRET:您從第三方服務產生的 OAuth 用戶端密鑰。
  • ORGANIZATION_ID:您的 Google Cloud 機構 ID。
  • PROJECT_NUMBER:您的 Google Cloud 專案編號。
  • ENGINE_ID:已部署的推理引擎代理程式 ID。
  • USER_EMAIL:您的個人使用者帳戶電子郵件地址。

設定 OAuth 用戶端應用程式

註冊 OAuth 用戶端憑證之前,請先從第三方授權伺服器 (例如 Google、GitHub 或 Jira) 取得用戶端 ID 和用戶端密鑰。

如要連線至Google Cloud以外的第三方服務,請從該服務的開發人員入口網站取得 OAuth 用戶端憑證,並略過本節中的步驟。

註冊重新導向 URI

設定 OAuth 用戶端憑證時,請務必註冊驗證供應商的專屬回呼重新導向 URI。

  1. 使用下列範本建構重新導向 URI:

    https://agentidentitycredentials.googleapis.com/v1alpha/projects/PROJECT_ID/locations/LOCATION/authProviders/AUTH_PROVIDER_NAME/oauthcallback

    更改下列內容:

    • PROJECT_ID: Google Cloud 專案 ID。
    • LOCATION:要部署驗證供應商的區域 (例如 us-west1)。
    • AUTH_PROVIDER_NAME:驗證供應商的名稱。

    例如:https://agentidentitycredentials.googleapis.com/v1alpha/projects/my-project/locations/us-west1/authProviders/bigquery-mcp-3lo-authprovider/oauthcallback

  2. 如要連線至 Google Cloud 服務 (例如 BigQuery),您可以在 Google Cloud 控制台中設定同意畫面,並建立 OAuth 用戶端憑證:

    1. 設定 OAuth 同意畫面:

      1. 在 Google Cloud 控制台中,前往「APIs & Services」(API 和服務)>「OAuth consent screen」(OAuth 同意畫面) 頁面。

        依序前往「APIs & Services」(API 和服務)>「OAuth consent screen」(OAuth 同意畫面)

      2. 在「應用程式資訊」部分,輸入應用程式名稱 (例如 BigQuery 管理員應用程式) 和支援電子郵件地址。
      3. 在「目標對象」部分,選取「內部」或「外部」
      4. 輸入聯絡資訊,即可接收通知。
      5. 詳閱並接受《Google API 服務使用者資料政策》。
      6. 按一下「完成」
    2. 建立 OAuth 用戶端憑證:

      1. 在 Google Cloud 控制台中,依序前往「API 和服務」>「OAuth 同意畫面」>「用戶端」頁面。

        依序前往「APIs & Services」(API 和服務) >「OAuth consent screen」(OAuth 同意畫面) >「Clients」(用戶端)

      2. 依序點選「建立憑證」>「OAuth 用戶端 ID」
      3. 從清單中選取「網頁應用程式」選項。
      4. 輸入 OAuth 用戶端的可辨識名稱。
      5. 在「已授權的重新導向 URI」部分,按一下「新增 URI」,然後輸入您建構的重新導向 URI。
      6. 點按「Create」(建立)。在「OAuth client created」(已建立 OAuth 用戶端) 對話方塊中,複製產生的「Client ID」(用戶端 ID) 和「Client Secret」(用戶端密碼) 值。

在代理程式碼中進行驗證

如要驗證代理程式,可以使用 ADK 或直接呼叫 Agent Identity API。

ADK

在 ADK 中使用 MCP 工具集,在代理的程式碼中參照驗證供應商。

from google.adk.agents.llm_agent import LlmAgent
from google.adk.auth.credential_manager import CredentialManager
from google.adk.integrations.agent_identity import GcpAuthProvider, GcpAuthProviderScheme
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
from google.adk.auth.auth_tool import AuthConfig

# Register Google Cloud auth provider
CredentialManager.register_auth_provider(GcpAuthProvider())

# The URI to redirect the user to after consent is granted.
CONTINUE_URI = "https://YOUR_FRONTEND_URL/validateUserId"

# Create auth provider scheme
# Note: If using the legacy V1 API, the resource name uses 'connectors'
# instead of 'authProviders': projects/.../connectors/...
auth_scheme = GcpAuthProviderScheme(
    name="projects/PROJECT_ID/locations/LOCATION/authProviders/AUTH_PROVIDER_NAME",
    continue_uri=CONTINUE_URI
)

# Configure an MCP tool with the authentication scheme.
toolset = McpToolset(
    connection_params=StreamableHTTPConnectionParams(url="https://YOUR_MCP_SERVER_URL"),
    auth_scheme=auth_scheme,
)

# Initialize the agent with the authenticated tools.
agent = LlmAgent(
    name="AGENT_NAME",
    model="gemini-2.5-flash",
    instruction="AGENT_INSTRUCTIONS",
    tools=[toolset],
)

範例:連結至 BigQuery MCP

以下範例顯示 agent.py 設定,可將代理連線至 BigQuery MCP 伺服器:

import os
from google.adk.agents import Agent
from google.adk.apps import App
from google.adk.auth.credential_manager import CredentialManager
from google.adk.integrations.agent_identity import GcpAuthProvider, GcpAuthProviderScheme
from google.adk.models import Gemini
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
import google.auth
from google.genai import types

_, project_id = google.auth.default()
os.environ["GOOGLE_CLOUD_PROJECT"] = "PROJECT_ID"
os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "True"

bigquery_mcp_auth_provider_id = "AUTH_PROVIDER_NAME"
bigquery_mcp_endpoint = os.environ.get(
    "BIGQUERY_MCP_ENDPOINT", "https://bigquery.googleapis.com/mcp"
)

# Register Google Cloud auth provider
CredentialManager.register_auth_provider(GcpAuthProvider())

# URI to redirect user to after consent is granted.
CONTINUE_URI = "http://127.0.0.1:8501/validateUserId"

bigquery_mcp_auth_scheme = GcpAuthProviderScheme(
    name=f"projects/{project_id}/locations/LOCATION/authProviders/{bigquery_mcp_auth_provider_id}",
    scopes=["https://www.googleapis.com/auth/bigquery"],
    continue_uri=CONTINUE_URI,
)

bigquery_mcp_tools = McpToolset(
    connection_params=StreamableHTTPConnectionParams(url=bigquery_mcp_endpoint),
    auth_scheme=bigquery_mcp_auth_scheme,
    errlog=None,
)

root_agent = Agent(
    name="root_agent",
    model=Gemini(
        model="gemini-2.5-flash",
        retry_options=types.HttpRetryOptions(attempts=3),
    ),
    instruction=(
        "You are a helpful AI assistant designed to provide accurate and useful"
        " information. You can also use your BigQuery MCP tools to look up"
        " BigQuery data."
    ),
    tools=[bigquery_mcp_tools],
)

app = App(
    root_agent=root_agent,
    name="AGENT_NAME",
)

ADK

在代理的程式碼中,使用 ADK 的已驗證函式工具參照驗證提供者。

import httpx
from google.adk.agents.llm_agent import LlmAgent
from google.adk.auth.credential_manager import CredentialManager
from google.adk.integrations.agent_identity import GcpAuthProvider
from google.adk.integrations.agent_identity import GcpAuthProviderScheme
from google.adk.apps import App
from google.adk.auth.auth_credential import AuthCredential
from google.adk.auth.auth_tool import AuthConfig
from google.adk.tools.authenticated_function_tool import AuthenticatedFunctionTool
from vertexai import agent_engines

# First, register Google Cloud auth provider
CredentialManager.register_auth_provider(GcpAuthProvider())

# The URI to redirect the user to after consent is completed.
CONTINUE_URI = "WEB_APP_VALIDATE_USER_URI"

# Create Auth Config
spotify_auth_config = AuthConfig(
    auth_scheme=GcpAuthProviderScheme(
        name="projects/PROJECT_ID/locations/LOCATION/authProviders/AUTH_PROVIDER_NAME",
        continue_uri=CONTINUE_URI
    )
)

# Use the Auth Config in Authenticated Function Tool
spotify_search_track_tool = AuthenticatedFunctionTool(
    func=spotify_search_track, auth_config=spotify_auth_config
)

# Sample function tool
async def spotify_search_track(credential: AuthCredential, query: str) -> str | list:
    token = None
    if credential.http and credential.http.credentials:
        token = credential.http.credentials.token

    if not token:
        return "Error: No authentication token available."

    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://api.spotify.com/v1/search",
            headers={"Authorization": f"Bearer {token}"},
            params={"q": query, "type": "track", "limit": 1},
        )
        # Add your own logic here

agent = LlmAgent(
    name="AGENT_NAME",
    model="gemini-2.5-flash",
    instruction="AGENT_INSTRUCTIONS",
    tools=[spotify_search_track_tool],
)

app = App(
    name="APP_NAME",
    root_agent=agent,
)

vertex_app = agent_engines.AdkApp(app_name=app)

ADK

在代理的程式碼中,使用 ADK 的 Agent Registry MCP 工具集參照驗證提供者。

from google.adk.agents.llm_agent import LlmAgent
from google.adk.auth.credential_manager import CredentialManager
from google.adk.integrations.agent_identity import GcpAuthProvider
from google.adk.integrations.agent_identity import GcpAuthProviderScheme
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
from google.adk.auth.auth_tool import AuthConfig
from google.adk.integrations.agent_registry import AgentRegistry

# First, register Google Cloud auth provider
CredentialManager.register_auth_provider(GcpAuthProvider())

# The URI to redirect the user to after consent is completed.
CONTINUE_URI="WEB_APP_VALIDATE_USER_URI"

# Create Google Cloud auth provider scheme
auth_scheme = GcpAuthProviderScheme(
    name="projects/PROJECT_ID/locations/LOCATION/authProviders/AUTH_PROVIDER_NAME",
    continue_uri=CONTINUE_URI
)

# Set Agent Registry
registry = AgentRegistry(project_id="PROJECT_ID", location="global")

toolset = registry.get_mcp_toolset(
    mcp_server_name=(
        "projects/PROJECT_ID/locations/"
        "global/mcpServers/"
        "agentregistry-00000000-0000-0000-0000-000000000000"
    ),
    auth_scheme=auth_scheme,
)

# Example MCP tool
toolset = McpToolset(
    connection_params=StreamableHTTPConnectionParams(url="MCP_URL"),
    auth_scheme=auth_scheme,
)

agent = LlmAgent(
    name="AGENT_NAME",
    model="MODEL_NAME",
    instruction="AGENT_INSTRUCTIONS",
    tools=[toolset],
)

直接呼叫 API

如果未使用 ADK,代理程式必須呼叫 agentidentitycredentials.retrieveCredentials API 才能取得權杖。

由於這是多步驟 OAuth 流程,因此代理程式必須處理作業的生命週期:

  1. 初始要求:代理程式會呼叫 retrieveCredentials
  2. 需要同意聲明:如果使用者尚未授予同意聲明,API 會傳回包含結果 uri_consent_required 的回應。這會包含 authorization_uriconsent_nonce
  3. 前端重新導向:應用程式必須將使用者重新導向至 authorization_uri
  4. 完成:使用者授予同意聲明後,請使用 consent_nonce 呼叫 FinalizeCredentials,完成流程並取得權杖。

更新用戶端應用程式

如要處理 3-legged OAuth 的使用者登入和重新導向作業,用戶端應用程式必須實作下列步驟,管理使用者同意聲明並繼續對話:

範例 UI 伺服器

您可以下載並執行使用 uvicorn 的完整範例 UI 伺服器。開始前,請確認您擁有 GitHub 帳戶,並已安裝 pip

如要設定及執行範例 UI 伺服器,請按照下列步驟操作:

  1. 複製 adk-python GitHub 存放區:

    git clone https://github.com/google/adk-python.git
  2. 前往存放區並啟動 Python 虛擬環境:

    cd adk-python
    python3 -m venv .venv
    source .venv/bin/activate
  3. 前往範例 UI 用戶端目錄:

    cd contributing/samples/integrations/gcp_auth/client
  4. 安裝用戶端依附元件:

    pip install -r requirements.txt
  5. 啟動伺服器前,請設定 AGENT_PROJECT_DIR 環境變數,指定代理程式程式碼所在的目錄。否則,應用程式預設會在用戶端目錄的上層資料夾中尋找代理程式。

    使用 uvicorn 啟動範例 UI 伺服器。確認通訊埠與 OAuth 用戶端中設定的重新導向 URI 相符:

    export AGENT_PROJECT_DIR="/path/to/your/agent_project"
    uvicorn main:app --port 8501 --reload
  6. 在瀏覽器中開啟 http://localhost:8501。(注意:您必須使用 localhost,而非 127.0.0.1,因為 OAuth 重新導向網址特別需要 localhost 主機名稱)。指定設定、按一下「儲存並套用設定」,然後與代理程式互動。

自訂 UI 應用程式

如要在自訂 UI 應用程式中直接實作這些功能,請按照下列步驟操作:

處理授權觸發程序

當代理程式需要使用者同意時,會傳回 adk_request_credential 函式呼叫。您的應用程式必須攔截這項呼叫,以啟動使用者授權對話方塊或重新導向。

記錄授權提供者提供的 consent_nonce,即可管理工作階段內容。驗證步驟需要這個隨機碼,才能驗證使用者。將 auth_configauth_request_function_call_id 值儲存在工作階段中,方便使用者授予同意聲明後繼續流程。

if (fc := get_auth_request_function_call(event_data)):
    print("--> Authentication required by agent.")
    try:
        auth_config = get_auth_config(fc)
        auth_uri, consent_nonce = handle_adk_request_credential(
            auth_config, AUTH_PROVIDER_NAME, request.user_id
        )
        if auth_uri:
            event_data['popup_auth_uri'] = auth_uri
            fc_id = (
                fc.get('id') if isinstance(fc, dict)
                else getattr(fc, 'id', None)
            )
            event_data['auth_request_function_call_id'] = fc_id
            event_data['auth_config'] = auth_config.model_dump()

            # Store session state
            if session_id:
                consent_sessions[session_id] = {
                    "user_id": request.user_id,
                    "consent_nonce": consent_nonce
                }
    except Exception as e:
        print(f"Error handling adk_request_credential: {e}")
        # Optionally, add logic to inform the user about the error.

def handle_adk_request_credential(auth_config, auth_provider_name, user_id):
    ec = auth_config.exchanged_auth_credential
    if ec and ec.oauth2:
        oauth2 = ec.oauth2
        return oauth2.auth_uri, oauth2.nonce
    return None, None

實作使用者驗證端點

在網頁伺服器上實作驗證端點 (與設定期間提供的 continue_uri 相同 URI)。這個端點必須符合下列條件:

  1. 以查詢參數形式接收 user_id_validation_stateauth_provider_nameuuid
  2. 從工作階段儲存空間擷取 user_idconsent_nonce 值。如果多個授權流程同時執行,請使用 uuid 比對正確的會期。
  3. 使用這些參數呼叫驗證供應商的 FinalizeCredentials API。
  4. 收到成功回應後,請關閉授權視窗。
範例:FastAPI 驗證端點 (main.py)

以下範例顯示完整的 FastAPI 驗證端點,可處理 OAuth 回呼並完成使用者憑證:

@app.api_route("/validateUserId", methods=["GET"])
async def validate_user(request: Request):
    auth_provider_name = request.query_params.get("auth_provider_name")
    session_id = request.cookies.get("session_id")
    session = consent_sessions.get(session_id, {})

    payload = {
        "userId": session.get("user_id"),
        "userIdValidationState": request.query_params.get(
            "user_id_validation_state"
        ),
        "consentNonce": session.get("consent_nonce"),
    }

    base_url = "https://agentidentitycredentials.googleapis.com/v1alpha"
    finalize_url = f"{base_url}/{auth_provider_name}/credentials:finalize"

    try:
        async with httpx.AsyncClient(timeout=30.0) as client:
            resp = await client.post(finalize_url, json=payload)
            resp.raise_for_status()
    except httpx.HTTPError as e:
        err_text = e.response.text if hasattr(e, "response") else str(e)
        status = e.response.status_code if hasattr(e, "response") else 500
        return HTMLResponse(err_text, status_code=status)

    return HTMLResponse("""
        <script>
            window.close();
        </script>
        <p>Success. You can close this window.</p>
    """)

繼續與服務專員對話

使用者授予同意聲明並關閉授權視窗後,請從工作階段資料中擷取 auth_configauth_request_function_call_id 值。如要繼續對話,請在向服務專員提出的新要求中,加入這些詳細資料做為 function_response

if (request.is_auth_resume and session.auth_request_function_call_id
    and session.auth_config):
    auth_content = types.Content(
        role='user',
        parts=[
            types.Part(
                function_response=types.FunctionResponse(
                    id=session.auth_request_function_call_id,
                    name='adk_request_credential',
                    response=session.auth_config
                )
            )
        ],
    )
    # Send message to agent
    async for event in agent.async_stream_query(
        user_id=request.user_id,
        message=auth_content,
        session_id=session_id,
    ):
        # ...

部署代理

將代理部署至 Google Cloud時,請務必啟用代理身分。

如要部署至 Gemini Enterprise Agent Platform 的 Agent Runtime ,請使用 identity_type=AGENT_IDENTITY 標記:

import vertexai
from vertexai import types
from vertexai.agent_engines import AdkApp

# Initialize the Vertex AI client with v1beta1 API for Agent Identity support
client = vertexai.Client(
    project="PROJECT_ID",
    location="LOCATION",
    http_options=dict(api_version="v1beta1")
)

# Use the proper wrapper class for your Agent Framework (e.g., AdkApp)
app = AdkApp(agent=agent)

# Deploy the agent with Agent Identity enabled
remote_app = client.agent_engines.create(
    agent=app,
    config={
        "identity_type": types.IdentityType.AGENT_IDENTITY,
        "requirements": [
            "google-cloud-aiplatform[agent_engines,adk]",
            "google-adk[agent-identity]"
        ],
    },
)

後續步驟