Skip to content

Commit da60e2f

Browse files
committed
fix(tools): support OpenAPI basic auth
1 parent 7de5bc5 commit da60e2f

2 files changed

Lines changed: 42 additions & 12 deletions

File tree

src/google/adk/tools/openapi_tool/auth/auth_helpers.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
from __future__ import annotations
1616

17+
import base64
18+
1719
from typing import Any
1820
from typing import Dict
1921
from typing import List
@@ -387,16 +389,25 @@ def credential_to_param(
387389
}
388390
return param, kwargs
389391
elif (
390-
auth_credential
391-
and auth_credential.http
392+
auth_credential.http
393+
and auth_credential.http.scheme.lower() == "basic"
392394
and auth_credential.http.credentials
393-
and (
394-
auth_credential.http.credentials.username
395-
or auth_credential.http.credentials.password
396-
)
395+
and auth_credential.http.credentials.username is not None
396+
and auth_credential.http.credentials.password is not None
397397
):
398-
# Basic Auth is explicitly NOT supported
399-
raise NotImplementedError("Basic Authentication is not supported.")
398+
credentials = auth_credential.http.credentials
399+
encoded_credentials = base64.b64encode(
400+
f"{credentials.username}:{credentials.password}".encode("utf-8")
401+
).decode("ascii")
402+
param = ApiParameter(
403+
original_name="Authorization",
404+
param_location="header",
405+
param_schema=Schema(type="string"),
406+
description=auth_scheme.description or "Basic authentication",
407+
py_name=INTERNAL_AUTH_PREFIX + "Authorization",
408+
)
409+
kwargs = {param.py_name: f"Basic {encoded_credentials}"}
410+
return param, kwargs
400411
else:
401412
raise ValueError("Invalid HTTP auth credentials")
402413

tests/unittests/tools/openapi_tool/auth/test_auth_helper.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import base64
1516
from unittest.mock import patch
1617

1718
from fastapi.openapi.models import APIKey
@@ -411,7 +412,7 @@ def test_credential_to_param_http_bearer():
411412
assert kwargs == {INTERNAL_AUTH_PREFIX + "Authorization": "Bearer test_token"}
412413

413414

414-
def test_credential_to_param_http_basic_not_supported():
415+
def test_credential_to_param_http_basic():
415416
auth_scheme = HTTPBase(scheme="basic")
416417
auth_credential = AuthCredential(
417418
auth_type=AuthCredentialTypes.HTTP,
@@ -421,9 +422,27 @@ def test_credential_to_param_http_basic_not_supported():
421422
),
422423
)
423424

424-
with pytest.raises(
425-
NotImplementedError, match="Basic Authentication is not supported."
426-
):
425+
param, kwargs = credential_to_param(auth_scheme, auth_credential)
426+
427+
expected_credentials = base64.b64encode(b"user:password").decode("ascii")
428+
assert param.original_name == "Authorization"
429+
assert param.param_location == "header"
430+
assert kwargs == {
431+
INTERNAL_AUTH_PREFIX + "Authorization": f"Basic {expected_credentials}"
432+
}
433+
434+
435+
def test_credential_to_param_http_basic_missing_password():
436+
auth_scheme = HTTPBase(scheme="basic")
437+
auth_credential = AuthCredential(
438+
auth_type=AuthCredentialTypes.HTTP,
439+
http=HttpAuth(
440+
scheme="basic",
441+
credentials=HttpCredentials(username="user"),
442+
),
443+
)
444+
445+
with pytest.raises(ValueError, match="Invalid HTTP auth credentials"):
427446
credential_to_param(auth_scheme, auth_credential)
428447

429448

0 commit comments

Comments
 (0)