-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Description
🔴 Required Information
Describe the Bug:
When using SAP Concur OAuth2 (authorization code flow) with
token_endpoint_auth_method="client_secret_post", ADK fails to exchange the
authorization code to Concur and logs:
Failed to exchange authorization code: 'str' object has no attribute 'get'
This indicates ADK is receiving a string where it expects a token dict.
Steps to Reproduce:
- Configure Concur OAuth2 with
token_endpoint_auth_method="client_secret_post". - Complete the authorize flow and receive
codefrom Concur. - Let ADK exchange the code.
- Observe the error above.
Expected Behavior:
ADK should successfully exchange the authorization code and store tokens
(access_token, refresh_token, expires_in, etc).
Proposed Fix:
When token_endpoint_auth_method == "client_secret_post", do not pass
client_id explicitly to fetch_token(). Let Authlib include it in the POST
body. Keep existing behavior for client_secret_basic.
Observed Behavior:
Environment Details:
- ADK Library Version (pip show google-adk): 1.24.0
- Desktop OS:** N/A (server environment)
- Python Version (python -V): Python 3.11.13
Model Information:
- Are you using LiteLLM: No
- Which model is being used: N/A
🟡 Optional Information
Providing this information greatly speeds up the resolution process.
Regression:
Additional Context:
We can reproduce a related issue using a minimal Authlib OAuth2Session script:
when token_endpoint_auth_method="client_secret_post" and client_id is passed
explicitly to fetch_token(), Concur returns:
"Received vectorized value :client_id=[\"<id>\" \"<id>\"]"
This suggests that if ADK passes client_id while using client_secret_post,
it may cause unexpected token responses or parsing issues.
Minimal Reproduction Code:
from authlib.integrations.requests_client import OAuth2Session
session = OAuth2Session(
client_id="<id>",
client_secret="<secret>",
token_endpoint="https://glz.api.concursolutions.com/oauth2/v0/token",
token_endpoint_auth_method="client_secret_post",
)
# Passing client_id here duplicates it in the POST body:
tokens = session.fetch_token(
"https://glz.api.concursolutions.com/oauth2/v0/token",
code="<auth_code>",
grant_type="authorization_code",
redirect_uri="<redirect_uri>",
client_id="<id>",
)How often has this issue occurred?:
- Always (100%)