Authenticate to Azure OpenAI Without API Keys: Python and TypeScript SDK Guide

The Old Way vs The New Way

Most Azure OpenAI tutorials start the same way: grab an API key from the Azure portal, paste it into an environment variable, and pass it to the SDK. It works, but it means you have a secret sitting in your deployment config that can leak, get committed, or go stale.

The identity-based approach uses Entra ID tokens instead. Your application proves who it is through a managed identity (in Azure) or your local Azure CLI session (during development), and the SDK handles the token lifecycle automatically. No keys anywhere.

This post shows both approaches side by side in Python and TypeScript so you can see exactly what changes.

How DefaultAzureCredential Works

DefaultAzureCredential is a credential chain from the Azure Identity library. It tries multiple authentication methods in order and uses the first one that succeeds:

This means the same code works locally (using your Azure CLI login) and in production (using the managed identity attached to your compute resource). No if-else logic, no environment-specific credential handling.

Python: API Key vs Managed Identity

First, install the required packages:

Here's what API key authentication looks like:

And here's the same thing with managed identity:

The key difference: instead of passing api_key, you pass azure_ad_token_provider. The get_bearer_token_provider function creates a callable that DefaultAzureCredential uses to fetch and refresh tokens automatically. The scope https://cognitiveservices.azure.com/.default tells Entra ID which API you're requesting access to.

TypeScript: API Key vs Managed Identity

Install the packages:

API key approach:

Managed identity approach:

Same pattern as Python: swap apiKey for azureADTokenProvider. The credential chain handles the rest.

Local Development Setup

DefaultAzureCredential works locally through your Azure CLI session. Make sure you're logged in and your account has the Cognitive Services OpenAI User role on the target resource:

Once you deploy to Azure with a managed identity that has the same role assignment, the code works without any changes. DefaultAzureCredential will automatically pick up the managed identity instead of Azure CLI.

Common Pitfalls

Wrong scope. The scope must be https://cognitiveservices.azure.com/.default for all Cognitive Services. Using the wrong scope returns a 401 even if your role assignment is correct.

Missing role assignment. The managed identity (or your user account) needs the Cognitive Services OpenAI User role on the specific OpenAI resource. Subscription-level Reader or Contributor roles are not enough.

Role propagation delay. After creating a role assignment, it can take up to 10 minutes to propagate. If you get a 403 right after assigning the role, wait a few minutes and try again.

DefaultAzureCredential in containers. If you're running in a Docker container locally, Azure CLI credentials are not available inside the container by default. Use environment variables with a service principal, or mount the Azure CLI token cache.

Further Reading

For more details, see the Azure OpenAI Python quickstart and the DefaultAzureCredential documentation.

Daniel Moquist

Author

May 06, 2025

Daniel Moquist

Cloud Architect & DevOps Expert