<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Managed Identity on Journey through Cloud &amp; Code</title><link>https://gurupasupathy.com/tags/managed-identity/</link><description>Recent content in Managed Identity on Journey through Cloud &amp; Code</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Wed, 20 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://gurupasupathy.com/tags/managed-identity/index.xml" rel="self" type="application/rss+xml"/><item><title>Choosing the Right TokenCredential and How AZURE CLIENT ID Influences Identity Selection — A…</title><link>https://gurupasupathy.com/post/2026-05-20_choosing-the-right-tokencredential-and-how-azure-client-id-influences-identity-selection/</link><pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate><guid>https://gurupasupathy.com/post/2026-05-20_choosing-the-right-tokencredential-and-how-azure-client-id-influences-identity-selection/</guid><description>&lt;p&gt;Photo by Matt Halls on Unsplash&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://cdn-images-1.medium.com/max/800/1*Z-K3Yu80zshHVrnXpLJ0FA.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@matthalls?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Matt Halls&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-very-tall-building-with-lots-of-windows-KeQiUCKNqOc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="introduction"&gt;Introduction&lt;/h4&gt;
&lt;p&gt;I have been using the DefaultAzureCredential class for a long time without understanding how it works. So, I jotted down my notes and learnings in this write-up for future me — and maybe you will find it useful too.&lt;/p&gt;
&lt;h4 id="tokencredential"&gt;TokenCredential&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;TokenCredential&lt;/code&gt; is the abstract base class representing a source of authentication tokens for Azure services. Many classes derive from TokenCredential but the most interesting ones are DefaultAzureCredential and ChainedTokenCredential.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Photo by Matt Halls on Unsplash</p>
<p><img loading="lazy" src="https://cdn-images-1.medium.com/max/800/1*Z-K3Yu80zshHVrnXpLJ0FA.jpeg"></p>
<p>Photo by <a href="https://unsplash.com/@matthalls?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Matt Halls</a> on <a href="https://unsplash.com/photos/a-very-tall-building-with-lots-of-windows-KeQiUCKNqOc?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
<h4 id="introduction">Introduction</h4>
<p>I have been using the DefaultAzureCredential class for a long time without understanding how it works. So, I jotted down my notes and learnings in this write-up for future me — and maybe you will find it useful too.</p>
<h4 id="tokencredential">TokenCredential</h4>
<p><code>TokenCredential</code> is the abstract base class representing a source of authentication tokens for Azure services. Many classes derive from TokenCredential but the most interesting ones are DefaultAzureCredential and ChainedTokenCredential.</p>
<blockquote>
<p>I’m using package version :Azure.Identity v1.20.0</p>
</blockquote>
<h4 id="defaultazurecredential">DefaultAzureCredential</h4>
<p>This class is a pre-built chain covering the most common authentication methods. When using DefaultAzureCredential to acquire a token, the class attempts to acquire a token via each of the below credentials, in the following order, stopping when one provides a token:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.environmentcredential?view=azure-dotnet">EnvironmentCredential</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.workloadidentitycredential?view=azure-dotnet">WorkloadIdentityCredential</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.managedidentitycredential?view=azure-dotnet">ManagedIdentityCredential</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.visualstudiocredential?view=azure-dotnet">VisualStudioCredential</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.visualstudiocodecredential?view=azure-dotnet">VisualStudioCodeCredential</a> (enabled by default for SSO with VS Code on supported platforms when Azure.Identity.Broker is installed)</li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.azureclicredential?view=azure-dotnet">AzureCliCredential</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.azurepowershellcredential?view=azure-dotnet">AzurePowerShellCredential</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.azuredeveloperclicredential?view=azure-dotnet">AzureDeveloperCliCredential</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.interactivebrowsercredential?view=azure-dotnet">InteractiveBrowserCredential</a> (not included by default; can use brokered authentication if Azure.Identity.Broker is installed)</li>
</ul>
<blockquote>
<p>source: <a href="https://learn.microsoft.com/en-us/dotnet/api/azure.identity.defaultazurecredential?view=azure-dotnet">DefaultAzureCredential Class (Azure.Identity) — Azure for .NET Developers | Microsoft Learn</a></p>
</blockquote>
<h4 id="defaultazurecredential-with-exclusion">DefaultAzureCredential with Exclusion</h4>
<p>DefaultAzureCredential also supports options that allow you to exclude credentials from evaluation. This is useful if you don’t want to use certain credentials, for example, when running my function locally, I don’t want to use the VisualStudio or VisualStudioCode credential as I prefer AzureCliCredential.</p>
<p>new DefaultAzureCredential(<br>
new DefaultAzureCredentialOptions<br>
{<br>
ExcludeVisualStudioCodeCredential = true,<br>
ExcludeVisualStudioCredential = true<br>
});</p>
<h4 id="chainedtokencredential">ChainedTokenCredential</h4>
<p>In some cases, you will know exactly which credentials you want to use. ChainedTokenCredential is very useful in such cases. It evaluates only the credentials you explicitly specify, in the order provided. I use this locally. For example, below I choose to use only CLI and VS credentials when my function is running locally.</p>
<p>new ChainedTokenCredential(<br>
new AzureCliCredential(),<br>
new VisualStudioCredential()<br>
));</p>
<h4 id="why-managed-identity-fails-locally-but-works-inazure">Why Managed Identity fails locally but works in Azure</h4>
<p><code>DefaultAzureCredential</code> attempts ManagedIdentityCredential (which is unavailable locally — IMDS timeout) and falls through to developer credentials — VS, CLI, etc (refer the table above). The first credential in the chain that can successfully acquire a token is used.</p>
<blockquote>
<p>Note: DefaultAzureCredential evaluates<br>
EnvironmentCredential, then WorkloadIdentityCredential,<br>
followed by ManagedIdentityCredential.</p>
</blockquote>
<p>There is no native way to emulate or impersonate a managed identity locally. IMDS (<code>169.254.169.254</code>) is a hypervisor-level endpoint that only exists on Azure compute. It is physically not present on your laptop. The common alternative would be to use a service principal with similar privileges as the UAMI to test your function.</p>
<p><strong>In Azure:</strong> The chain gets to <code>ManagedIdentityCredential</code>, IMDS responds, token acquired. Everything below it never runs.</p>
<p><strong>Locally:</strong> IMDS doesn’t exist, so <code>ManagedIdentityCredential</code> times out and falls through.</p>
<p>When DefaultAzureCredential is used, the evaluation would like this (assuming none of the credentials are able to provide a token) —</p>
<p>//When running locally there is no IMDS to supply managed identity token<br>
//Assuming VS and other credentials don&rsquo;t have access to the resource.<br>
//This is how DefaultAzureCredentials evaluates the chain<br>
EnvironmentCredential → skipped (env vars not set)<br>
WorkloadIdentityCredential → skipped (not configured)<br>
ManagedIdentityCredential → unavailable/failure (no IMDS endpoint locally)<br>
VisualStudioCredential → failed <br>
VisualStudioCodeCredential → failed<br>
AzureCliCredential → failed<br>
AzurePowerShellCredential → failed<br>
AzureDeveloperCliCredential → failed<br>
InteractiveBrowserCredential → Not included by default (must be explicitly enabled)</p>
<h4 id="how-to-configure-for-local-debugging">How to configure for local debugging</h4>
<p>One approach is to use a factory that returns different credential implementations depending on the execution environment.</p>
<p>For example, when the environment is local, a factory can return a DefaultAzureCredential where you can exclude Visual Studio and Visual Studio Code credentials if you favour AzureCliCredential. Or, better still, if you want to use only Azure CLI or VS credentials, it can return a ChainedTokenCredential with just those two credentials, as shown below</p>
<p>new ChainedTokenCredential(<br>
new AzureCliCredential(),<br>
new VisualStudioCredential()<br>
)</p>
<p>When the environment is Azure, it can just return a DefaultAzureCredential instance or a ChainedTokenCredential as discussed earlier if you are sure about the credential you want to use. If you want to use a specific credential, it can be used directly without DefaultAzureCredential or ChainedTokenCredential. For example, here I’m using a specific credential class —</p>
<p>new ManagedIdentityCredential(<br>
ManagedIdentityId.FromUserAssignedClientId(&laquo;your-uami-ClientId&raquo;)))</p>
<p>A sample flow will look as below when you use a ChainedTokenCredential as shown previously —</p>
<p>AzureCliCredential → acquire token - SUCCESS<br>
VisualStudioCredential → skipped</p>
<p>Notice that only the two credentials mentioned in the <code>ChainedTokenCredential</code> chain are evaluated.</p>
<h4 id="azure_client_id-influence-in-identity-selection">AZURE_CLIENT_ID influence in identity selection</h4>
<p>Many Azure resources can have both System Assigned Managed Identity (SAMI) and User Assigned Managed Identity (UAMI). It is crucial to understand how the AZURE_CLIENT_ID environment variable influences how Azure SDK authentication selects a managed identity. This is not always obvious, and I could not find it clearly documented anywhere</p>
<p>AZURE_CLIENT_ID set?<br>
│<br>
├── YES<br>
│   │<br>
│   └── Which credential in code?<br>
│       │<br>
│       ├── DefaultAzureCredential()<br>
│       │   └── ✅ UAMI  (via AZURE_CLIENT_ID)<br>
│       │<br>
│       ├── ManagedIdentityCredential(id)<br>
│       │   └── ✅ UAMI  (via explicit id, ignores AZURE_CLIENT_ID)<br>
│       │<br>
│       └── ManagedIdentityCredential()<br>
│           └── ⚠️  SAMI  (ignores AZURE_CLIENT_ID)<br>
│<br>
└── NO<br>
│<br>
└── Which credential in code?<br>
│<br>
├── DefaultAzureCredential()<br>
│   └── ⚠️  SAMI<br>
│<br>
├── ManagedIdentityCredential(id)<br>
│   └── ✅ UAMI  (via explicit id)<br>
│<br>
└── ManagedIdentityCredential()<br>
└── ⚠️  SAMI  (no id provided)</p>
<p>Key rule: ManagedIdentityCredential() does not use<br>
AZURE_CLIENT_ID to select a user-assigned managed identity.<br>
Only DefaultAzureCredential does</p>
<p>Note: the flowchart assumes a System Assigned Managed Identity is present. In cases where SAMI is absent and no UAMI is explicitly provided, token acquisition will fail</p>
<blockquote>
<p>Authentication between a Function App and its AzureWebJobsStorage is an independent flow not covered by the flowchart above. See [<a href="https://pasupathy-guru.medium.com/using-managed-identity-for-function-app-authentication-with-its-storage-account-ad352a609abe?source=friends_link&amp;sk=c97ecbf3bbdb14ff8dc7318a70355f3a">Using Managed Identity for Function App Authentication with its Storage Account</a>] for a detailed walkthrough.</p>
</blockquote>
<h4 id="summary">Summary</h4>
<p><code>DefaultAzureCredential</code> is environment-aware by design — the same code uses managed identity in Azure and falls through to developer credentials locally. This means local failures don&rsquo;t always predict Azure failures, and the identity that succeeds locally may be in a different tenant than your Azure resources. For local testing against tenant-specific resources, ensure <code>az login --tenant &lt;tenant-id&gt;</code> is used explicitly, not just any <code>az login</code>. To test managed identity behaviour you must deploy, or substitute a service principal with matching roles via <code>EnvironmentCredential</code>.</p>
<p>Reference — <a href="https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication/best-practices?tabs=aspdotnet">Authentication best practices with the Azure Identity library for .NET — .NET | Microsoft Learn</a></p>
]]></content:encoded></item><item><title>Using Managed Identity for Function App Authentication with its Storage account</title><link>https://gurupasupathy.com/post/2026-05-19_using-mi-for-function-app-authentication-with-its-storage-account/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://gurupasupathy.com/post/2026-05-19_using-mi-for-function-app-authentication-with-its-storage-account/</guid><description>&lt;p&gt;Recently, while setting up a Function App to use User Assigned Managed Identity (UAMI) to authenticate to its &lt;strong&gt;AzureWebJobsStorage&lt;/strong&gt; I encountered &lt;code&gt;SyncTrigger&lt;/code&gt;failure.&lt;/p&gt;
&lt;p&gt;I checked whether the UAMI had necessary RBAC roles to work on &lt;strong&gt;AzureWebJobsStorage&lt;/strong&gt; — it had. So, I wasn’t sure what the issue was.&lt;/p&gt;
&lt;p&gt;Analyzing further, I realized I had skipped a few mandatory variable settings to enable UAMI based authentication to &lt;strong&gt;AzureWebJobsStorage&lt;/strong&gt; (setting the environment variable &lt;code&gt;AzureWebJobsStorage__accountName&lt;/code&gt; alone does not suffice)&lt;/p&gt;</description><content:encoded><![CDATA[<p>Recently, while setting up a Function App to use User Assigned Managed Identity (UAMI) to authenticate to its <strong>AzureWebJobsStorage</strong> I encountered <code>SyncTrigger</code>failure.</p>
<p>I checked whether the UAMI had necessary RBAC roles to work on <strong>AzureWebJobsStorage</strong> — it had. So, I wasn’t sure what the issue was.</p>
<p>Analyzing further, I realized I had skipped a few mandatory variable settings to enable UAMI based authentication to <strong>AzureWebJobsStorage</strong> (setting the environment variable <code>AzureWebJobsStorage__accountName</code> alone does not suffice)</p>
<h4 id="steps-to-enable-uami-access-to-azurewebjobsstorage">Steps to enable UAMI access to <strong>AzureWebJobsStorage</strong></h4>
<p>Enabling UAMI access to AzureWebJobStorage involves changes in Terraform (when the Function App is created), the App Settings (Environment variables) and finally the Role Based Access.</p>
<p><strong>Terraform</strong></p>
<p>If for some reason you want to use UAMI to authenticate with <strong>AzureWebJobsStorage</strong>, then <strong>Terraform</strong> block <code>**functionAppConfig.deployment.storage.authentication**</code><strong>:</strong> should look like below</p>
<blockquote>
<p>Note: I am using Flex Consumption tier</p>
</blockquote>
<p>authentication = {<br>
type                           = &ldquo;userassignedidentity&rdquo;<br>
userAssignedIdentityResourceId = &ldquo;<full ARM resource ID of UAMI>&rdquo;<br>
}</p>
<p>This tells the platform to use UAMI for the deployment package blob container — the part that isn’t controlled by app settings.</p>
<p><strong>App settings</strong></p>
<p>Once the Function App is deployed with usermanagedidentity as authentication type (terraform), ensure the below variables are set in the Function App’s Environment variables</p>
<p>AzureWebJobsStorage__accountName  = <storage account name><br>
AzureWebJobsStorage__credential   = managedidentity<br>
AzureWebJobsStorage__clientId     = <UAMI client ID GUID></p>
<p>All three settings are mandatory.</p>
<p><strong>RBAC</strong></p>
<p>This is the final bit. We have the Function App deployed, environment variables set, next, the UAMI needs privilege to access the storage account.</p>
<p>Provide <code>Storage Blob Data Owner</code> owner role to the UAMI on the storage account</p>
<p>With these three changes, your Function App will authenticate with its <strong>AzureWebJobsStorage</strong> using UAMI.</p>
<blockquote>
<p><strong><em>Caveat</em></strong>: Although this works, the issue with this approach is all services that are assigned this UAMI will gain access to the function’s storage account. This is not ideal if many services share the same UAMI. The better option will be to use System Assigned Managed Identity (SAMI) for authentication between Function App and its storage account. For the rest of the outbound calls that the functions might make, use UAMI.</p>
</blockquote>
<h4 id="using-system-assigned-managedidentity">Using System Assigned Managed Identity</h4>
<p>To use SAMI just set<code>AzureWebJobsStorage__accountName</code> — SAMI is the default, no additional settings needed. Next, give SAMI <code>Storage Blob Data Owner</code> on the storage account. If you are using Terraform to deploy the authentication block of the Function App will look like this —</p>
<p>authentication = {<br>
type = &ldquo;systemassignedidentity&rdquo;<br>
}</p>
<p>SAMI is my preferred method for authentication with the <strong>AzureWebJobsStorage</strong> for the reasons already discussed in the caveat section.</p>
<h4 id="summary">Summary</h4>
<p>Configuring a Function App to authenticate with its AzureWebJobsStorage using managed identity requires changes at three levels — Terraform, app settings, and RBAC — and all three must be consistent with each other. For UAMI, all three <code>AzureWebJobsStorage__*</code> settings are mandatory; omitting any one of them will cause the runtime to fail. However, personally I feel UAMI for AzureWebJobsStorage is rarely the right choice — since UAMI is a shared identity, every service assigned to it inherits access to the storage account. SAMI, which requires only <code>AzureWebJobsStorage__accountName</code> and a single role assignment, is the simpler and safer default for this use case.</p>
<blockquote>
<p>Reference — <a href="https://techcommunity.microsoft.com/blog/appsonazureblog/use-user-managed-identity-to-replace-connection-string-inazurewebjobsstorage-for/3891026">Use User managed identity to replace connection string in”AzureWebJobsStorage” for function apps | Microsoft Community Hub</a></p>
</blockquote>
]]></content:encoded></item><item><title>Adding application roles to Managed Identity</title><link>https://gurupasupathy.com/post/2026-02-27_adding-application-roles-to-managed-identity/</link><pubDate>Fri, 27 Feb 2026 00:00:00 +0000</pubDate><guid>https://gurupasupathy.com/post/2026-02-27_adding-application-roles-to-managed-identity/</guid><description>&lt;p&gt;&lt;img loading="lazy" src="https://gurupasupathy.com/img/1__932kIAgBM7f5RkLN3QcYxw.png"&gt;&lt;/p&gt;
&lt;p&gt;This guide outlines the process for assigning application roles to a &lt;strong&gt;Managed Identity (MI)&lt;/strong&gt; in Entra ID. It covers observed behaviors, inherent limitations, and the necessary steps required when an MI must authenticate with another application (such as an API in APIM) using role-based access control (RBAC).&lt;/p&gt;
&lt;h3 id="scenario"&gt;Scenario&lt;/h3&gt;
&lt;p&gt;In a typical architecture, a &lt;strong&gt;Logic App&lt;/strong&gt; utilizes a &lt;strong&gt;Managed Identity&lt;/strong&gt; (either System-Assigned or User-Assigned) to communicate with downstream resources. When that Logic App needs to call an &lt;strong&gt;API exposed via APIM&lt;/strong&gt;, the following requirements usually apply:&lt;/p&gt;</description><content:encoded><![CDATA[<p><img loading="lazy" src="/img/1__932kIAgBM7f5RkLN3QcYxw.png"></p>
<p>This guide outlines the process for assigning application roles to a <strong>Managed Identity (MI)</strong> in Entra ID. It covers observed behaviors, inherent limitations, and the necessary steps required when an MI must authenticate with another application (such as an API in APIM) using role-based access control (RBAC).</p>
<h3 id="scenario">Scenario</h3>
<p>In a typical architecture, a <strong>Logic App</strong> utilizes a <strong>Managed Identity</strong> (either System-Assigned or User-Assigned) to communicate with downstream resources. When that Logic App needs to call an <strong>API exposed via APIM</strong>, the following requirements usually apply:</p>
<ul>
<li>The API is protected by its own <strong>App Registration</strong> in Entra ID.</li>
<li>The API expects the caller to possess specific <strong>app roles</strong> (e.g., <code>API.Read</code> or <code>API.ReadWrite</code>).</li>
<li>The Logic App must obtain an OAuth token containing these roles to successfully authorize against the API.</li>
</ul>
<h3 id="the-challenge">The Challenge</h3>
<p>Managed Identities are automatically created Service Principals. A common point of confusion is that they <strong>do not appear in the App Registration section</strong> of the Azure portal; they are found exclusively under <strong>Enterprise Applications</strong>.</p>
<p>Because the Azure portal does not currently provide a UI for assigning app roles to Enterprise Applications directly, it is not possible to assign roles like <code>API.Read</code> through the standard &ldquo;API Permissions&rdquo; blade used for traditional App Registrations.</p>
<h3 id="the-workaroundassigning-app-roles-via-powershell--microsoft-graph">The Workaround — Assigning App Roles via PowerShell / Microsoft Graph</h3>
<p>You can use the below Powershell to assign roles to your Managed Identity</p>
<p># Install-Module Microsoft.Graph -Scope CurrentUser (If not done already)</p>
<p># Your tenant ID (in the Azure portal, under Azure Active Directory &gt; Overview).<br>
$tenantID = &lsquo;{tenantId}&rsquo;</p>
<p># The name of the server app that exposes the app roles.<br>
$serverApplicationName = &lsquo;{serverApplicationName}&rsquo;</p>
<p># The name of the app role that the managed identity should be assigned to.<br>
$appRoleName = &lsquo;{appRoleName}&rsquo; # For example, Api.Read</p>
<p># Look up the Logic App / Function (Client application) managed identity&rsquo;s object ID.<br>
$managedIdentityObjectId = &lsquo;{managedIdentityObjectId}&rsquo;</p>
<p># Connect-MgGraph -TenantId $tenantId -Scopes &lsquo;Application.ReadWrite.All&rsquo;,&lsquo;Directory.Read.All&rsquo;<br>
# or a more restricted set of permissions (recommended):<br>
Connect-MgGraph -TenantId $tenantId -Scopes &lsquo;Application.Read.All&rsquo;,&lsquo;AppRoleAssignment.ReadWrite.All&rsquo;</p>
<p># Look up the details about the server app&rsquo;s service principal and app role.<br>
$serverServicePrincipal = (Get-MgServicePrincipal -Filter &ldquo;DisplayName eq &lsquo;$serverApplicationName&rsquo;&rdquo;)<br>
$serverServicePrincipalObjectId = $serverServicePrincipal.Id<br>
$appRoleId = ($serverServicePrincipal.AppRoles | Where-Object {$_.Value -eq $appRoleName }).Id</p>
<p>Write-Host &lsquo;$serverServicePrincipal &rsquo; $serverServicePrincipal<br>
Write-Host &lsquo;$managedIdentityObjectId &rsquo; $managedIdentityObjectId<br>
Write-Host &lsquo;$serverServicePrincipalObjectId &rsquo; $serverServicePrincipalObjectId<br>
Write-Host &lsquo;AppRoleId &gt;&rsquo; $appRoleId</p>
<p># Assign the managed identity access to the app role.<br>
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $serverServicePrincipalObjectId -PrincipalId $managedIdentityObjectId -ResourceId $serverServicePrincipalObjectId -AppRoleId $appRoleId</p>
<ul>
<li><code>PrincipalId</code> → Managed Identity object ID (Logic App)</li>
<li><code>ResourceId</code> → API service principal object ID</li>
<li><code>AppRoleId</code> → GUID of the role defined in the API registration</li>
</ul>
<p>After this assignment, tokens requested by the Managed Identity will include the required <code>roles</code> claim, allowing successful authorization against the API.</p>
<h3 id="note">Note</h3>
<ul>
<li>For clientId to be able to be used as an audience it must “own” App Roles. And the consumer-client-id should have been provided this roles in AAD. I think you can further check these claims in the Authentication section</li>
</ul>
<h3 id="key-takeaways">Key Takeaways</h3>
<ul>
<li>Managed Identities always appear as <strong>Enterprise Apps</strong> in Azure AD.</li>
<li>App roles cannot be assigned via the portal for Enterprise Apps; <strong>Graph / PowerShell is required</strong>.</li>
<li>Token validation depends on correct <strong>Issuer, Audience, and presence of role claims</strong>.</li>
<li>Explicit role assignment ensures tokens carry the required roles for API authorization.</li>
</ul>
]]></content:encoded></item><item><title>Access AppConfiguration from Function App using Managed Identity</title><link>https://gurupasupathy.com/post/2026-02-21_access-appconfiguration-from-function-app-using-managed-identity/</link><pubDate>Sat, 21 Feb 2026 00:00:00 +0000</pubDate><guid>https://gurupasupathy.com/post/2026-02-21_access-appconfiguration-from-function-app-using-managed-identity/</guid><description>&lt;p&gt;&lt;img loading="lazy" src="https://gurupasupathy.com/img/1__nTaI7u53YGpj1No72IN6Yw.png"&gt;&lt;/p&gt;
&lt;p&gt;Accessing Azure App Configuration using Managed Identity in Azure Functions is slightly different from accessing other Azure services.&lt;/p&gt;
&lt;p&gt;For most Azure services (Storage, Service Bus, Key Vault), you typically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enable Managed Identity on the Function&lt;/li&gt;
&lt;li&gt;Grant RBAC access to the resource&lt;/li&gt;
&lt;li&gt;Create the SDK client using DefaultAzureCredential&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, App Configuration is usually loaded as part of the application configuration pipeline at startup, so it must be added via the host builder.&lt;/p&gt;</description><content:encoded><![CDATA[<p><img loading="lazy" src="/img/1__nTaI7u53YGpj1No72IN6Yw.png"></p>
<p>Accessing Azure App Configuration using Managed Identity in Azure Functions is slightly different from accessing other Azure services.</p>
<p>For most Azure services (Storage, Service Bus, Key Vault), you typically:</p>
<ul>
<li>Enable Managed Identity on the Function</li>
<li>Grant RBAC access to the resource</li>
<li>Create the SDK client using DefaultAzureCredential</li>
</ul>
<p>However, App Configuration is usually loaded as part of the application configuration pipeline at startup, so it must be added via the host builder.</p>
<h3 id="prerequisites">Prerequisites</h3>
<ul>
<li>Enable Managed Identity on the Function App</li>
<li>Grant the identity: App Configuration Data Reader on the App Configuration resource</li>
</ul>
<p>Sample code as shown below</p>
<p>var host = new HostBuilder()    <br>
.ConfigureAppConfiguration(builder =&gt;<br>
{<br>
string cs = Environment.GetEnvironmentVariable(&ldquo;ConnectionString&rdquo;);<br>
builder.AddAzureAppConfiguration(options =&gt;<br>
options.Connect(new Uri(@&ldquo;<a href="https://appconfiguri.azconfig.io">https://appconfiguri.azconfig.io</a>&rdquo;), new ManagedIdentityCredential()));<br>
})<br>
.ConfigureFunctionsWebApplication()<br>
.Build();<br>
host.Run();</p>
<p>Note: I’m using ManagedIdentityCredential but the recommend class is DefaultAzureCredential</p>
<h3 id="key-insight">Key Insight</h3>
<ul>
<li>Other Azure services → authenticated when <strong>creating the client</strong></li>
<li>App Configuration → authenticated when <strong>building the configuration provider.</strong> That’s why it must be configured inside <code>ConfigureAppConfiguration()</code>.</li>
</ul>
]]></content:encoded></item></channel></rss>