Authentication Tokens for Azure AI Foundry Data Agents through Entra Service Principal-Part 1

After pondering over Azure Foundry AI for last couple of weeks I decided to take the holy leap into the exciting world of Data Agents, focusing particularly on those linked to Azure AI Foundry.
So please look out for upcoming blogs covering this topic. I will be posting a quite few of them.
Why ClientSecretCredential for bearer tokens ?
The ClientSecretCredential class is used to authenticate a client application with a service (like Azure) using the OAuth 2.0 client credentials flow. This authentication flow results in a bearer token, which can then be used to access protected resources like Azure Key Vault, Azure Storage or other Microsoft and Azure services.
Almost all of Microsoft’s Data Agent authentication examples on Microsoft’s official documentations are revolved around DefaultAzureCredential but nothing around ClientSecretCredential.
To be fair, I am not a big fan of using DefaultAzureCredential. While using DefaultAzureCredential,you have to use ChainedTokenCredentials for an Azure service to be authenticated and one might lose track of which Azure service corresponds to which credentials and personally that can create a BIG mess.
With ClientSecretCredential, you have much better control and can easily trace out credentials that are specific for a given Azure service.
The only reason why I would use DefaultAzureCredential for any of the Azure services is when I want the Azure service authenticated through Azure Managed Identity or Azure Key Vault and that’s all. For everything else(for me) its alwaysClientSecretCredential.
Microsoft’s official documentation provides a brief overview of authorizing data agents using managed identities.
You can find that here : https://learn.microsoft.com/en-us/azure/ai-foundry/openai/how-to/managed-identity?source=recommendations#authorize-access-to-managed-identities
If you want to learn more about Azure Managed Identities, you can read up one of my articles on the topic that I blogged on last year
https://www.azureguru.net/managed-identities-in-microsoft-azure
But ClientSecretCredential is incompatible with Azure AI Foundry Data Agents
Not really.
You can use the ClientSecretCredential class with TokenCredentialto generate a token provider and send the token provider as argument to AIProjectClient as an AuthenticationTokenProvider.
But the above approach has big drawback. As we are using ClientSecretCredential class we would require clientSecret to be stored “somewhere” for instance in appsettings.json or an Environment variables.
Again am I not at all fan of this approach :)
If you have been following my blog which not many do :) , last year I had blogged on how we would NOT require the clientSecret stored anywhere and still be able to use ClientSecretCredential. This is achieved by converting the accesstoken to JwtSecurityToken which then act as a tokenCredential to the underlying Azure service.
Above article was specific for Azure storage DataLakeServiceClient.
In the Part 2 of this article I will explore how we can use JwtSecurityToken through ClientSecretCredential to authenticate using the same approach that was used for authenticating DataLakeServiceClient.
So stay tuned for Part 2 of this article.
Setup
To get started, first we will have to create a Azure AI Foundry project in https://ai.azure.com
The steps are pretty straightforward. You can find detailed steps here
https://learn.microsoft.com/en-us/azure/ai-foundry/how-to/create-projects?tabs=ai-foundry
Once you have done creating the project you will find the API keys and the endpoints.

But you might now argue that we have API keys then what’s the need for using ClientServiceCredentials for authentication. Just use to the API keys for the authentication.
Imagine where Azure AD wants to get authenticated for an Azure service say Azure AI Foundry and in turn the Azure Foundry is integrated with Azure Function. This cannot be implemented just by using API Keys.
And also Microsoft strongly recommends against the usage of Foundry API keys. Below is the screengrab from Microsoft’s recommendation against not using the API key.

So we will stick our approach of using the Entra authentication.
I will be using one of the existing Service Principal called Fabric MSAL that I always have used in all of my other articles.

The AI model that I have used is gpt-4.1

Now that we have the model and the endpoints ready, we will have to assign roles to the our Entra service Principal
Note :

Microsoft recommends assigning Search Index Data Contributor and Search Service Contributor roles.
I assigned these roles but it did not work. The code errored out during creation of agent due to insufficient permissions.

So I had revert it and I decided to assign the “Azure AI Project Manager” role.
You can assign it through the Azure portal or Azure CLI.

Through Azure CLI
az role assignment create --assignee "Your Service principal objectid"
--role "Azure AI Project Manager"
--scope "/subscriptions/{subscriptionid}/resourceGroups/ResourceGroup/providers/Microsoft.CognitiveServices/accounts/{resource name}"

Once we have all the required settings and permissions in place, we can now create a new C# Console application and add the following references/NuGet packages through the following .NET CLI commands.
dotnet add package Azure.Core --version 1.49.0
dotnet add package Azure.AI.Agents.Persistent --version 1.1.0
dotnet add package Azure.AI.Projects --version 1.0.0
dotnet add package Azure.Identity --version 1.16.0
In the next step declare few variables
string projectEndpoint = "Your AI foundry resource endpoint";
string modelDeploymentName = "gpt-4.1";
var tenantId = "Service Principal Tenant Id";
var clientId = "Service Principal Client Id";
var clientSecret = "Service Principal Client Secret";
Next, we define Token credentials and the scope.
For this article we will stick with https://cognitiveservices.azure.com/.default scope.
var cts = new CancellationTokenSource();
CancellationToken cancellationToken = cts.Token;
TokenCredential Tokencredentials = null;
Tokencredentials = new ClientSecretCredential(tenantId, clientId, clientSecret);
string[] scopes = new string[] { "https://cognitiveservices.azure.com/.default" };
AccessToken token = Tokencredentials.GetToken(new TokenRequestContext(scopes), cancellationToken);
Once the authentication token is generated, we proceed to authenticate the ProjectEndpoint with the generated token and define an ProjectClient and an AgentsClient.
AIProjectClient projectClient = new(new Uri(projectEndpoint), Tokencredentials);
PersistentAgentsClient agentsClient = projectClient.GetPersistentAgentsClient();
and then we create a Data Agent and an AgentThread
PersistentAgent agent = agentsClient.Administration.CreateAgent(
model: modelDeploymentName,
name: "My First AI foundry agent",
instructions: "You are the first Azure foundry AI Agent"
);
PersistentAgentThread thread = agentsClient.Threads.CreateThread();
Console.WriteLine(agent.Name + " at " + agent.CreatedAt.ToLocalTime().ToString());
and that’s all..
Execute the code and you will see an Data Agent created under https://ai.azure.com/resource/agentsList


Complete code :
using Azure;
using Azure.AI.Agents.Persistent;
using Azure.AI.Projects;
using Azure.Core;
using Azure.Identity;
namespace AzureAIConsoleApplication
{
internal class Program
{
public static void Main(string[] args)
{
string projectEndpoint = "Your AI foundry resource endpoint";
string modelDeploymentName = "gpt-4.1";
var tenantId = "Service Principal Tenant Id";
var clientId = "Service Principal Client Id";
var clientSecret = "Service Principal Client Secret";
Console.WriteLine("Creating access token at " + DateTime.Now.ToString());
Console.WriteLine("");
var cts = new CancellationTokenSource();
CancellationToken cancellationToken = cts.Token;
TokenCredential Tokencredentials = null;
Tokencredentials = new ClientSecretCredential(tenantId, clientId, clientSecret);
string[] scopes = new string[] { "https://cognitiveservices.azure.com/.default" };
AccessToken token = Tokencredentials.GetToken(new TokenRequestContext(scopes), cancellationToken);
Console.WriteLine("Created access token at " + DateTime.Now.ToString());
Console.WriteLine("");
Console.WriteLine("Creating ProjectClient and Data Agent at " + DateTime.Now.ToString());
Console.WriteLine("");
AIProjectClient projectClient = new(new Uri(projectEndpoint), Tokencredentials);
PersistentAgentsClient agentsClient = projectClient.GetPersistentAgentsClient();
PersistentAgent agent = agentsClient.Administration.CreateAgent(
model: modelDeploymentName,
name: "My First AI foundry agent",
instructions: "You are the first Azure foundry AI Agent"
);
PersistentAgentThread thread = agentsClient.Threads.CreateThread();
Console.WriteLine(agent.Name + " at " + agent.CreatedAt.ToLocalTime().ToString());
}
}
}
Conclusion
In this very first blog I have highlighted a crucial points regarding the authentication mechanism to be used in Azure AI Foundry.
API Keys – Simple, but Less Secure
Easy to set up and use.
Suitable for lightweight and non prod use cases.
Can be stored in Azure App Settings or Key Vault.
Risk: Can be compromised if not handled securely.
Service Principals – Secure and Scalable
Uses OAuth2 tokens with Service Principals or Managed Identities.
Ideal for production and enterprise environments.
Supports role-based access control (RBAC).
Enables use of
DefaultAzureCredentialandClientSecretCredentialin code.Very secure for all of the Azure’s integrated services.
Stay tuned for the second part on this topic.
Thanks for reading !!!




