Skip to content

fix: Unable to acquire impersonated credentials #2003

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

hsuyuming
Copy link
Contributor

add scope "https://www.googleapis.com/auth/cloud-platform" within google.auth.default

@hsuyuming
Copy link
Contributor Author

@hangfei @seanzhou1023
This is my PR in order to fix #2001, please help me review it, if there are any part need to be modified, please let me know. Thank you

@hsuyuming
Copy link
Contributor Author

hsuyuming commented Jul 16, 2025

Screenshot 2025-07-16 at 4 41 25 PM

@hangfei
Copy link
Collaborator

hangfei commented Jul 19, 2025

Thanks for the contribution. Please follow https://github.com/google/adk-python/blob/main/CONTRIBUTING.md.

@Allaway11
Copy link

We also are stuck at this point with authenticating with a service account. would be great to get this merged.

@hsuyuming
Copy link
Contributor Author

I will try to modify my PR before the end of this wek.

@hsuyuming hsuyuming force-pushed the fix/issue_2001_support_impersonated_credential branch 3 times, most recently from 1efbdae to 10e39b1 Compare July 25, 2025 18:28
@hsuyuming hsuyuming force-pushed the fix/issue_2001_support_impersonated_credential branch from 10e39b1 to 61c42db Compare July 25, 2025 18:36
@hsuyuming
Copy link
Contributor Author

hsuyuming commented Jul 25, 2025

Unit Test successfully result:

============================= test session starts ==============================
platform linux -- Python 3.12.10, pytest-8.4.1, pluggy-1.6.0
rootdir: /home/user/abehsu/adk-python-hsuyuming
configfile: pyproject.toml
plugins: asyncio-1.1.0, mock-3.14.1, anyio-4.9.0, langsmith-0.3.45, xdist-3.8.0
asyncio: mode=Mode.AUTO, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 3786 items

tests/unittests/a2a/converters/test_event_converter.py ................. [  0%]
...........................................................              [  2%]
tests/unittests/a2a/converters/test_part_converter.py .................. [  2%]
..................................................                       [  3%]
tests/unittests/a2a/converters/test_request_converter.py ............... [  4%]
...........                                                              [  4%]
tests/unittests/a2a/converters/test_utils.py ........................... [  5%]
.............                                                            [  5%]
tests/unittests/a2a/executor/test_a2a_agent_executor.py ................ [  5%]
..............................                                           [  6%]
......
tests/unittests/tools/test_from_function_with_options.py ............... [ 90%]
.                                                                        [ 90%]
tests/unittests/tools/test_function_tool.py ............................ [ 91%]
..........                                                               [ 91%]
tests/unittests/tools/test_gemini_schema_util.py ....................... [ 91%]
........................................................................ [ 93%]
.................                                                        [ 94%]
tests/unittests/tools/test_google_search_tool.py ....................... [ 94%]
...............                                                          [ 95%]
tests/unittests/tools/test_langchain_tool.py ........                    [ 95%]
tests/unittests/tools/test_long_running_tool.py ....................     [ 96%]
tests/unittests/tools/test_url_context_tool.py ......................... [ 96%]
.....                                                                    [ 96%]
tests/unittests/tools/test_vertex_ai_search_tool.py .................... [ 97%]
..................                                                       [ 97%]
tests/unittests/utils/test_feature_decorator.py ........................ [ 98%]
..                                                                       [ 98%]
tests/unittests/utils/test_instructions_utils.py ......................  [ 99%]
tests/unittests/utils/test_model_name_utils.py ......................... [ 99%]
.........                                                                [100%]
================ 3786 passed, 2100 warnings in 67.78s (0:01:07) ================

End to End testing result:

Impersonated testing (before fix)
  • gcloud settings
(adk_with_different_auth) user@abehsu-us-vscode:~/abehsu/adk_with_different_auth$ gcloud config list
[auth]
impersonate_service_account = shared-service-account@<gcp project>.iam.gserviceaccount.com
[core]
account = xxxxx
disable_usage_reporting = True
project = <gcp project>

Your active configuration is: [gcp project]
  • application_default_credentials.json
(adk-python-hsuyuming) user@abehsu-us-vscode:~/abehsu/adk_with_different_auth/oauth2/apihub_tools$ cat ~/.config/gcloud/application_default_credentials.json 
{
  "delegates": [],
  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/shared-service-account@xxxxxx.iam.gserviceaccount.com:generateAccessToken",
  "source_credentials": {
    "account": "",
    "client_id": "xxxxxxx",
    "client_secret": "xxxxx",
    "refresh_token": "xxxxxx",
    "type": "authorized_user",
    "universe_domain": "googleapis.com"
  },
  "type": "impersonated_service_account"
}
  • testing code
from google.adk.tools.apihub_tool.apihub_toolset import APIHubToolset
from google.adk.agents.llm_agent import LlmAgent

userinfo_toolset = APIHubToolset(
  name="enterprise_assistant",
  description="enterprise assistant tool",
  #  api: abehsu_test
  apihub_resource_name="projects/<gcp project>/locations/us-west1/apis/<resource>", # API Hub resource name
)

# --- Agent Configuration ---
# Configure and create the main LLM Agent.
root_agent = LlmAgent(
    model='gemini-2.0-flash',
    name='enterprise_assistant',
    instruction='Help user integrate with multiple enterprise systems, including retrieving user information which may require authentication.',
    tools=[userinfo_toolset],
)
  • lunch adk web
adk web
  • user start communication
Screenshot 2025-07-25 at 12 57 00 PM
  • error log
(adk-python-hsuyuming) user@abehsu-us-vscode:~/abehsu/adk_with_different_auth/oauth2$ adk web
/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/cli/fast_api.py:365: UserWarning: [EXPERIMENTAL] InMemoryCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time.
  credential_service = InMemoryCredentialService()
/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/auth/credential_service/in_memory_credential_service.py:33: UserWarning: [EXPERIMENTAL] BaseCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time.
  super().__init__()
INFO:     Started server process [17416]
INFO:     Waiting for application startup.

+-----------------------------------------------------------------------------+
| ADK Web Server started                                                      |
|                                                                             |
| For local testing, access at http://localhost:8000.                         |
+-----------------------------------------------------------------------------+

INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     127.0.0.1:60566 - "GET / HTTP/1.1" 307 Temporary Redirect
INFO:     127.0.0.1:60566 - "GET /dev-ui/ HTTP/1.1" 200 OK
INFO:     127.0.0.1:60566 - "GET /dev-ui/main-SRBSE46V.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:60560 - "GET /dev-ui/chunk-EQDQRRRY.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:60576 - "GET /dev-ui/styles-4VDSPQ37.css HTTP/1.1" 200 OK
INFO:     127.0.0.1:60578 - "GET /dev-ui/polyfills-B6TNHZQ6.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:60578 - "GET /dev-ui/assets/config/runtime-config.json HTTP/1.1" 200 OK
INFO:     127.0.0.1:60576 - "GET /dev-ui/assets/ADK-512-color.svg HTTP/1.1" 200 OK
INFO:     127.0.0.1:60578 - "GET /list-apps?relative_path=./ HTTP/1.1" 200 OK
2025-07-25 18:49:16,256 - INFO - fast_api.py:486 - New session created
INFO:     127.0.0.1:60578 - "POST /apps/apihub_tools/users/user/sessions HTTP/1.1" 200 OK
INFO:     127.0.0.1:60566 - "GET /apps/apihub_tools/eval_results HTTP/1.1" 200 OK
INFO:     127.0.0.1:60576 - "GET /apps/apihub_tools/eval_sets HTTP/1.1" 200 OK
INFO:     127.0.0.1:60578 - "GET /apps/apihub_tools/users/user/sessions HTTP/1.1" 200 OK
INFO:     127.0.0.1:60578 - "GET /apps/apihub_tools/users/user/sessions HTTP/1.1" 200 OK
INFO:     127.0.0.1:60578 - "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 Not Found
INFO:     127.0.0.1:36404 - "POST /run_sse HTTP/1.1" 200 OK
2025-07-25 18:49:27,687 - INFO - envs.py:47 - Loaded .env file for apihub_tools at /home/user/abehsu/adk_with_different_auth/oauth2/apihub_tools/.env
2025-07-25 18:49:27,688 - INFO - envs.py:47 - Loaded .env file for apihub_tools at /home/user/abehsu/adk_with_different_auth/oauth2/apihub_tools/.env
2025-07-25 18:49:28,951 - ERROR - fast_api.py:889 - Error in event_generator: ("Fail to load 'apihub_tools' module. Unable to acquire impersonated credentials", '{\n  "error": {\n    "code": 400,\n    "message": "Request contains an invalid argument.",\n    "status": "INVALID_ARGUMENT"\n  }\n}\n')
Traceback (most recent call last):
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/cli/fast_api.py", line 876, in event_generator
    runner = await _get_runner_async(req.app_name)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/cli/fast_api.py", line 1027, in _get_runner_async
    root_agent = agent_loader.load_agent(app_name)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/cli/utils/agent_loader.py", line 198, in load_agent
    agent = self._perform_load(agent_name)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/cli/utils/agent_loader.py", line 172, in _perform_load
    if root_agent := self._load_from_module_or_package(agent_name):
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/cli/utils/agent_loader.py", line 92, in _load_from_module_or_package
    raise e
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/cli/utils/agent_loader.py", line 60, in _load_from_module_or_package
    module_candidate = importlib.import_module(agent_name)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/share/uv/python/cpython-3.12.10-linux-x86_64-gnu/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 999, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/home/user/abehsu/adk_with_different_auth/oauth2/apihub_tools/__init__.py", line 1, in <module>
    from . import agent
  File "/home/user/abehsu/adk_with_different_auth/oauth2/apihub_tools/agent.py", line 6, in <module>
    userinfo_toolset = APIHubToolset(
                       ^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/tools/apihub_tool/apihub_toolset.py", line 149, in __init__
    self._prepare_toolset()
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/tools/apihub_tool/apihub_toolset.py", line 169, in _prepare_toolset
    spec_str = self._apihub_client.get_spec_content(self._apihub_resource_name)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/tools/apihub_tool/clients/apihub_client.py", line 95, in get_spec_content
    api = self.get_api(apihub_resource_name)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/tools/apihub_tool/clients/apihub_client.py", line 151, in get_api
    "Authorization": f"Bearer {self._get_access_token()}",
                               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/adk/tools/apihub_tool/clients/apihub_client.py", line 339, in _get_access_token
    credentials.refresh(Request())
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/auth/impersonated_credentials.py", line 260, in refresh
    self._update_token(request)
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/auth/impersonated_credentials.py", line 325, in _update_token
    self.token, self.expiry = _make_iam_token_request(
                              ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/abehsu/adk_with_different_auth/.venv/lib/python3.12/site-packages/google/auth/impersonated_credentials.py", line 100, in _make_iam_token_request
    raise exceptions.RefreshError(_REFRESH_ERROR, response_body)
google.auth.exceptions.RefreshError: ("Fail to load 'apihub_tools' module. Unable to acquire impersonated credentials", '{\n  "error": {\n    "code": 400,\n    "message": "Request contains an invalid argument.",\n    "status": "INVALID_ARGUMENT"\n  }\n}\n')
INFO:     127.0.0.1:36404 - "GET /apps/apihub_tools/users/user/sessions/c06b7454-696f-4ab5-890f-8d535f6701b0 HTTP/1.1" 200 OK
INFO:     127.0.0.1:36414 - "GET /debug/trace/session/c06b7454-696f-4ab5-890f-8d535f6701b0 HTTP/1.1" 200 OK
Impersonated testing (after fix)
  • gcloud settings
(adk_with_different_auth) user@abehsu-us-vscode:~/abehsu/adk_with_different_auth$ gcloud config list
[auth]
impersonate_service_account = shared-service-account@<gcp project>.iam.gserviceaccount.com
[core]
account = xxxxx
disable_usage_reporting = True
project = <gcp project>

Your active configuration is: [gcp project]
  • lunch adk web
adk web
  • no error appear
Screenshot 2025-07-25 at 1 03 52 PM

normal account testing (after fix)

  • gcloud config settings
(adk-python-hsuyuming) user@abehsu-us-vscode:~/abehsu/adk_with_different_auth/oauth2/apihub_tools$ gcloud config list
[core]
account = <account>
disable_usage_reporting = True
project = <gcp project>

Your active configuration is: [gdw-dev-apigee-user]
  • application_default_credentials.json
(adk-python-hsuyuming) user@abehsu-us-vscode:~/abehsu/adk_with_different_auth/oauth2/apihub_tools$ cat ~/.config/gcloud/application_default_credentials.json 
{
  "account": "",
  "client_id": "xxxxx",
  "client_secret": "xxxx",
  "quota_project_id": "xxxxx",
  "refresh_token": "xxxxx",
  "type": "authorized_user",
  "universe_domain": "googleapis.com"
}
  • lunch adk web
adk web
  • successfully result
Screenshot 2025-07-25 at 1 13 54 PM

@hsuyuming
Copy link
Contributor Author

Hi @hangfei :
I update my PR to reach all of the requirements within CONTRIBUTING.md, can you help me review once?

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.

3 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy