Skip to content

Commit ffe062a

Browse files
committed
fix(client): allow explicit empty API key
1 parent 38d75d7 commit ffe062a

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

src/openai/_client.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class OpenAI(SyncAPIClient):
106106
api_key: str
107107
admin_api_key: str | None
108108
workload_identity: WorkloadIdentity | None
109+
_api_key_is_set: bool
109110
organization: str | None
110111
project: str | None
111112
webhook_secret: str | None
@@ -165,13 +166,15 @@ def __init__(
165166

166167
if workload_identity is not None:
167168
self.api_key = WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER
169+
self._api_key_is_set = True
168170
self._api_key_provider = None
169171
self._workload_identity_auth = WorkloadIdentityAuth(
170172
workload_identity=workload_identity,
171173
)
172174
else:
173175
if api_key is None:
174176
api_key = os.environ.get("OPENAI_API_KEY")
177+
self._api_key_is_set = api_key is not None
175178
if callable(api_key):
176179
self.api_key = ""
177180
self._api_key_provider: Callable[[], str] | None = api_key # type: ignore[no-redef]
@@ -186,7 +189,7 @@ def __init__(
186189

187190
if (
188191
_enforce_credentials
189-
and not self.api_key
192+
and not self._api_key_is_set
190193
and self._api_key_provider is None
191194
and workload_identity is None
192195
and self.admin_api_key is None
@@ -489,6 +492,9 @@ def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
489492
if _has_header(headers, "Authorization") or _has_omitted_header(custom_headers, "Authorization"):
490493
return
491494

495+
if self._api_key_is_set and not self.api_key:
496+
return
497+
492498
raise TypeError(
493499
'"Could not resolve authentication method. Expected either api_key or admin_api_key to be set. Or for one of the `Authorization` or `Authorization` headers to be explicitly omitted"'
494500
)
@@ -612,6 +618,7 @@ class AsyncOpenAI(AsyncAPIClient):
612618
api_key: str
613619
admin_api_key: str | None
614620
workload_identity: WorkloadIdentity | None
621+
_api_key_is_set: bool
615622
organization: str | None
616623
project: str | None
617624
webhook_secret: str | None
@@ -671,13 +678,15 @@ def __init__(
671678

672679
if workload_identity is not None:
673680
self.api_key = WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER
681+
self._api_key_is_set = True
674682
self._api_key_provider = None
675683
self._workload_identity_auth = WorkloadIdentityAuth(
676684
workload_identity=workload_identity,
677685
)
678686
else:
679687
if api_key is None:
680688
api_key = os.environ.get("OPENAI_API_KEY")
689+
self._api_key_is_set = api_key is not None
681690
if callable(api_key):
682691
self.api_key = ""
683692
self._api_key_provider: Callable[[], Awaitable[str]] | None = api_key # type: ignore[no-redef]
@@ -692,7 +701,7 @@ def __init__(
692701

693702
if (
694703
_enforce_credentials
695-
and not self.api_key
704+
and not self._api_key_is_set
696705
and self._api_key_provider is None
697706
and workload_identity is None
698707
and self.admin_api_key is None
@@ -995,6 +1004,9 @@ def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
9951004
if _has_header(headers, "Authorization") or _has_omitted_header(custom_headers, "Authorization"):
9961005
return
9971006

1007+
if self._api_key_is_set and not self.api_key:
1008+
return
1009+
9981010
raise TypeError(
9991011
'"Could not resolve authentication method. Expected either api_key or admin_api_key to be set. Or for one of the `Authorization` or `Authorization` headers to be explicitly omitted"'
10001012
)

tests/test_client.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,16 @@ def test_validate_headers(self) -> None:
498498
"OPENAI_ADMIN_KEY": Omit(),
499499
}
500500
):
501+
local_server = OpenAI(
502+
base_url=base_url,
503+
api_key="",
504+
admin_api_key=None,
505+
_strict_response_validation=True,
506+
)
507+
local_server_request = local_server._build_request(FinalRequestOptions(method="get", url="/foo"))
508+
assert "Authorization" not in local_server_request.headers
509+
local_server.close()
510+
501511
no_credentials = OpenAI(
502512
base_url=base_url,
503513
api_key=None,
@@ -1762,6 +1772,16 @@ async def test_validate_headers(self) -> None:
17621772
"OPENAI_ADMIN_KEY": Omit(),
17631773
}
17641774
):
1775+
local_server = AsyncOpenAI(
1776+
base_url=base_url,
1777+
api_key="",
1778+
admin_api_key=None,
1779+
_strict_response_validation=True,
1780+
)
1781+
local_server_request = local_server._build_request(FinalRequestOptions(method="get", url="/foo"))
1782+
assert "Authorization" not in local_server_request.headers
1783+
await local_server.close()
1784+
17651785
no_credentials = AsyncOpenAI(
17661786
base_url=base_url,
17671787
api_key=None,

0 commit comments

Comments
 (0)