-
Notifications
You must be signed in to change notification settings - Fork 5.2k
fix(azure): treat JWT-like api_key as Bearer token for AAD authentication #3783
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
base: main
Are you sure you want to change the base?
Changes from all commits
1edcfa1
4eee6b3
a4bc984
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -56,6 +56,13 @@ def _has_auth_header(headers: Headers) -> bool: | |
| return _has_header(headers, "Authorization") or _has_header(headers, "api-key") | ||
|
|
||
|
|
||
| def _is_jwt(token: str) -> bool: | ||
| """Check if a token looks like a JWT (used for Azure AD tokens).""" | ||
| # JWT tokens have three parts separated by dots: header.payload.signature | ||
| # The header is base64-encoded and typically starts with "eyJ" for RS256/HS256 tokens | ||
| return token.startswith("eyJ") and token.count(".") == 2 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For Realtime connections using a JWT-like AGENTS.md reference: AGENTS.md:L41-L45 Useful? React with 👍 / 👎. |
||
|
|
||
|
|
||
| _AZURE_AUTH_ORIGIN = "openai.azure_auth_origin" | ||
|
|
||
|
|
||
|
|
@@ -459,6 +466,9 @@ def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: # noqa: A | |
| return {"Authorization": f"Bearer {self._azure_ad_token}"} | ||
|
|
||
| if self.api_key and self.api_key != API_KEY_SENTINEL: | ||
| # If api_key looks like a JWT (Azure AD token), send as Bearer | ||
| if _is_jwt(self.api_key): | ||
| return {"Authorization": f"Bearer {self.api_key}"} | ||
|
Comment on lines
+470
to
+471
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a JWT-like value is supplied through AGENTS.md reference: AGENTS.md:L41-L45 Useful? React with 👍 / 👎. |
||
| return {"api-key": self.api_key} | ||
|
|
||
| return {} | ||
|
|
@@ -813,6 +823,9 @@ def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: # noqa: A | |
| return {"Authorization": f"Bearer {self._azure_ad_token}"} | ||
|
|
||
| if self.api_key and self.api_key != API_KEY_SENTINEL: | ||
| # If api_key looks like a JWT (Azure AD token), send as Bearer | ||
| if _is_jwt(self.api_key): | ||
| return {"Authorization": f"Bearer {self.api_key}"} | ||
| return {"api-key": self.api_key} | ||
|
|
||
| return {} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a subject-token exchange returns a missing, nonnumeric, nonpositive, or nonfinite
expires_in, this changes the established failure fromOpenAIErrortoValueError, unlike the other malformed token-response fields handled immediately above. Applications catching SDK authentication errors can therefore unexpectedly receive an uncaught built-in exception; retainOpenAIErrorwhile performing the stricter validation and cover synchronous and asynchronous exchange paths.AGENTS.md reference: AGENTS.md:L41-L45
Useful? React with 👍 / 👎.