Skip to main content

Command Palette

Search for a command to run...

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

Updated
7 min read
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.

https://www.azureguru.net/customize-clientsecretcredential-class-for-onelake-authentication-in-microsoft-fabric

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.

Azure AI Foundry

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.

Azure AI Foundry

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.

Azure AI Foundry

The AI model that I have used is gpt-4.1

Azure AI Foundry

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

Note :

Azure AI Foundry

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.

Azure AI Foundry

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.

Azure AI Foundry

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}"

Azure AI Foundry

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.

💡
The scope should always be : https://cognitiveservices.azure.com/.default But the scope will change in my second article. I will explain why in the second article of this topic.

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

Azure AI Foundry

Azure AI Foundry

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 DefaultAzureCredential and ClientSecretCredential in code.

  • Very secure for all of the Azure’s integrated services.

Stay tuned for the second part on this topic.

Thanks for reading !!!

More from this blog

My Ramblings On Microsoft Data Stack

83 posts

From Azure Synapse Analytics, Power BI, Azure Data Factory, Spark and Microsoft Fabric I explore all aspects of the Microsoft Data Stack in this blog.