Skip to content

Commit ee0e109

Browse files
feat(api): add bearer token auth
1 parent 7a72928 commit ee0e109

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

.stats.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
configured_endpoints: 65
22
openapi_spec_hash: eeb8ebc5600523bdfad046381a929572
3-
config_hash: 63e520502003839482d0dbeb82132064
3+
config_hash: 14b2643a0ec60cf326dfed00939644ff

src/codex/_client.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class Codex(SyncAPIClient):
6363
with_streaming_response: CodexWithStreamedResponse
6464

6565
# client options
66+
auth_token: str | None
6667
api_key: str | None
6768
access_key: str | None
6869

@@ -71,6 +72,7 @@ class Codex(SyncAPIClient):
7172
def __init__(
7273
self,
7374
*,
75+
auth_token: str | None = None,
7476
api_key: str | None = None,
7577
access_key: str | None = None,
7678
environment: Literal["production", "staging", "local"] | NotGiven = NOT_GIVEN,
@@ -94,6 +96,8 @@ def __init__(
9496
_strict_response_validation: bool = False,
9597
) -> None:
9698
"""Construct a new synchronous Codex client instance."""
99+
self.auth_token = auth_token
100+
97101
self.api_key = api_key
98102

99103
self.access_key = access_key
@@ -151,7 +155,14 @@ def qs(self) -> Querystring:
151155
@property
152156
@override
153157
def auth_headers(self) -> dict[str, str]:
154-
return {**self._authenticated_api_key, **self._public_access_key}
158+
return {**self._http_bearer, **self._authenticated_api_key, **self._public_access_key}
159+
160+
@property
161+
def _http_bearer(self) -> dict[str, str]:
162+
auth_token = self.auth_token
163+
if auth_token is None:
164+
return {}
165+
return {"Authorization": f"Bearer {auth_token}"}
155166

156167
@property
157168
def _authenticated_api_key(self) -> dict[str, str]:
@@ -178,6 +189,11 @@ def default_headers(self) -> dict[str, str | Omit]:
178189

179190
@override
180191
def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
192+
if self.auth_token and headers.get("Authorization"):
193+
return
194+
if isinstance(custom_headers.get("Authorization"), Omit):
195+
return
196+
181197
if self.api_key and headers.get("X-API-Key"):
182198
return
183199
if isinstance(custom_headers.get("X-API-Key"), Omit):
@@ -189,12 +205,13 @@ def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
189205
return
190206

191207
raise TypeError(
192-
'"Could not resolve authentication method. Expected either api_key or access_key to be set. Or for one of the `X-API-Key` or `X-Access-Key` headers to be explicitly omitted"'
208+
'"Could not resolve authentication method. Expected one of auth_token, api_key or access_key to be set. Or for one of the `Authorization`, `X-API-Key` or `X-Access-Key` headers to be explicitly omitted"'
193209
)
194210

195211
def copy(
196212
self,
197213
*,
214+
auth_token: str | None = None,
198215
api_key: str | None = None,
199216
access_key: str | None = None,
200217
environment: Literal["production", "staging", "local"] | None = None,
@@ -231,6 +248,7 @@ def copy(
231248

232249
http_client = http_client or self._client
233250
return self.__class__(
251+
auth_token=auth_token or self.auth_token,
234252
api_key=api_key or self.api_key,
235253
access_key=access_key or self.access_key,
236254
base_url=base_url or self.base_url,
@@ -291,6 +309,7 @@ class AsyncCodex(AsyncAPIClient):
291309
with_streaming_response: AsyncCodexWithStreamedResponse
292310

293311
# client options
312+
auth_token: str | None
294313
api_key: str | None
295314
access_key: str | None
296315

@@ -299,6 +318,7 @@ class AsyncCodex(AsyncAPIClient):
299318
def __init__(
300319
self,
301320
*,
321+
auth_token: str | None = None,
302322
api_key: str | None = None,
303323
access_key: str | None = None,
304324
environment: Literal["production", "staging", "local"] | NotGiven = NOT_GIVEN,
@@ -322,6 +342,8 @@ def __init__(
322342
_strict_response_validation: bool = False,
323343
) -> None:
324344
"""Construct a new async AsyncCodex client instance."""
345+
self.auth_token = auth_token
346+
325347
self.api_key = api_key
326348

327349
self.access_key = access_key
@@ -379,7 +401,14 @@ def qs(self) -> Querystring:
379401
@property
380402
@override
381403
def auth_headers(self) -> dict[str, str]:
382-
return {**self._authenticated_api_key, **self._public_access_key}
404+
return {**self._http_bearer, **self._authenticated_api_key, **self._public_access_key}
405+
406+
@property
407+
def _http_bearer(self) -> dict[str, str]:
408+
auth_token = self.auth_token
409+
if auth_token is None:
410+
return {}
411+
return {"Authorization": f"Bearer {auth_token}"}
383412

384413
@property
385414
def _authenticated_api_key(self) -> dict[str, str]:
@@ -406,6 +435,11 @@ def default_headers(self) -> dict[str, str | Omit]:
406435

407436
@override
408437
def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
438+
if self.auth_token and headers.get("Authorization"):
439+
return
440+
if isinstance(custom_headers.get("Authorization"), Omit):
441+
return
442+
409443
if self.api_key and headers.get("X-API-Key"):
410444
return
411445
if isinstance(custom_headers.get("X-API-Key"), Omit):
@@ -417,12 +451,13 @@ def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
417451
return
418452

419453
raise TypeError(
420-
'"Could not resolve authentication method. Expected either api_key or access_key to be set. Or for one of the `X-API-Key` or `X-Access-Key` headers to be explicitly omitted"'
454+
'"Could not resolve authentication method. Expected one of auth_token, api_key or access_key to be set. Or for one of the `Authorization`, `X-API-Key` or `X-Access-Key` headers to be explicitly omitted"'
421455
)
422456

423457
def copy(
424458
self,
425459
*,
460+
auth_token: str | None = None,
426461
api_key: str | None = None,
427462
access_key: str | None = None,
428463
environment: Literal["production", "staging", "local"] | None = None,
@@ -459,6 +494,7 @@ def copy(
459494

460495
http_client = http_client or self._client
461496
return self.__class__(
497+
auth_token=auth_token or self.auth_token,
462498
api_key=api_key or self.api_key,
463499
access_key=access_key or self.access_key,
464500
base_url=base_url or self.base_url,

0 commit comments

Comments
 (0)