microsoft/semantic-kernel · error · ServiceInitializationError
No API key or Azure AD token available for ephemeral token…
Error message
No API key or Azure AD token available for ephemeral token request.
What it means
Raised by AzureRealtimeWebRTC._get_ephemeral_token_headers_and_url(). This method builds the auth headers for the ephemeral token request to the Azure Realtime client_secrets endpoint. It checks self.client.api_key (must be set and not the '<missing API key>' sentinel) and self.client._azure_ad_token (must be non-None). If neither is available, there is no credential to attach to the request. Notably, this method does NOT check for ad_token_provider — only static api_key and static ad_token are supported for ephemeral token retrieval.
Solutions
- Provide an api_key when constructing AzureRealtimeWebRTC — the ephemeral token endpoint accepts key-based auth.
- Provide a static ad_token (pre-fetched Azure AD token string) instead of only an ad_token_provider.
- If you must use a token provider, pre-resolve the token yourself and pass it as ad_token=<resolved_token>.
- If using a pre-built client, ensure it was constructed with api_key= or azure_ad_token= (not just azure_ad_token_provider=).
Example fix
# before (token provider only — ephemeral token path cannot use it)
service = AzureRealtimeWebRTC(
audio_track=my_track,
endpoint='https://myresource.openai.azure.com',
deployment_name='gpt-4o-realtime',
ad_token_provider=my_provider_func, # no static key or token
)
# after (pass api_key for ephemeral token auth)
service = AzureRealtimeWebRTC(
audio_track=my_track,
endpoint='https://myresource.openai.azure.com',
deployment_name='gpt-4o-realtime',
api_key=os.environ['AZURE_OPENAI_API_KEY'],
) Defensive patterns
Strategy: validation
Validate before calling
def validate_webrtc_auth(api_key, ad_token, ad_token_provider, async_client):
"""The AzureRealtimeWebRTC ephemeral token path only supports static api_key or static ad_token.
An ad_token_provider alone is not sufficient for the ephemeral token request."""
if async_client is not None:
# Client handles its own auth — but verify it has a key or static token
return
if not api_key and not ad_token:
if ad_token_provider:
raise ValueError(
'AzureRealtimeWebRTC ephemeral token endpoint requires api_key or static ad_token. '
'An ad_token_provider alone is not supported. Pre-resolve the token and pass as ad_token.'
)
raise ValueError('api_key or ad_token is required for AzureRealtimeWebRTC')
validate_webrtc_auth(api_key, ad_token, ad_token_provider, async_client) Try / catch
from semantic_kernel.exceptions.service_exceptions import ServiceInitializationError
try:
token = await service._get_ephemeral_token()
except ServiceInitializationError as e:
if 'No API key or Azure AD token' in str(e):
# Reconstruct the service with api_key or a pre-resolved ad_token
print('WebRTC ephemeral token requires static api_key or ad_token, not a provider.')
raise Prevention
- Pass api_key when using AzureRealtimeWebRTC — the ephemeral token path checks static credentials only.
- If using Entra ID, pre-resolve the token with get_entra_auth_token() and pass it as ad_token=.
- Avoid relying solely on ad_token_provider for WebRTC realtime.
- If passing a pre-built client, ensure it has api_key= or azure_ad_token= set (not just azure_ad_token_provider=).
When it happens
Trigger: Constructing AzureRealtimeWebRTC with only an ad_token_provider (no static api_key, no static ad_token). The AsyncAzureOpenAI client is configured with a callable token provider, so client.api_key is unset and client._azure_ad_token is None at the time this method runs. Also possible if a pre-built async_client was passed that has neither a key nor a static token.
Common situations: Using Azure managed identity (DefaultAzureCredential with a token provider callback) for WebRTC realtime; passing a bare AsyncAzureOpenAI client built elsewhere that relies on a provider; migrating from key-based auth to Entra ID auth and forgetting that the WebRTC ephemeral-token path only checks static credentials.
Related errors
- Failed to get ephemeral token
- Audio is required for InputAudioBufferAppendEvent
- Audio track not initialized
- Failed to create OpenAI settings.
- Failed to create OpenAI settings.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/1a777155f61005fd.
Report an issue: GitHub.
Appendix: source
Thrown at python/semantic_kernel/connectors/ai/open_ai/services/azure_realtime.py:340
url = f"{endpoint}/openai/v1/realtime/client_secrets"
if self.client.api_key and self.client.api_key != "<missing API key>":
return (
{
"api-key": self.client.api_key,
"Content-Type": "application/json",
},
url,
)
if self.client._azure_ad_token is not None: # type: ignore[attr-defined]
return (
{
"Authorization": f"Bearer {self.client._azure_ad_token}", # type: ignore[attr-defined]
"Content-Type": "application/json",
},
url,
)
raise ServiceInitializationError("No API key or Azure AD token available for ephemeral token request.")
@override
async def _get_ephemeral_token(self) -> str:
"""Get an ephemeral token from Azure OpenAI.
Azure GA requires a nested session object:
{"session": {"type": "realtime", "model": "<deployment>"}}
And returns the token directly as {"value": "..."} rather than
OpenAI's {"client_secret": {"value": "..."}}.
See: https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/realtime-audio-webrtc
"""
data = {
"session": {
"type": "realtime",
"model": self.ai_model_id,
}
}
headers, url = self._get_ephemeral_token_headers_and_url()View on GitHub (pinned to c028a0c7dc)