Authenticate to Entra ID Protected APIs with Managed Identity—No Key Vault Required
Last updated on November 10, 2024
A common way of authenticating to APIs, such as Microsoft Graph, has been that you set up an application registration in Entra ID, and create a client secret or a certificate. Then you store that sensitive information in an Azure Key Vault and have your application fetch it from there using its managed identity. After that, you’d use that fetched piece of information for authenticating to the API in your code. But did you know that there’s also an alternative way, which allows us to skip creating the application registration, client secret/certificate, and Azure Key Vault entirely?
We can allow our applications to authenticate to Entra ID protected APIs directly with the application managed identity. We don’t need to have a client secret or a certificate, and we can get rid of the risk of those pieces of sensitive information getting leaked. Otherwise, it works seemingly the same way by allowing us to use APIs with application permissions; it is just more secure.
Managed identity is not a new feature, and I know a few people have already blogged about this topic in the past. Still, I continue to run into developers who are not familiar with this approach. Based on my experience, it is clear that this method requires more exposure, which is why I am here writing about it for you. I hope you’ll find this article useful, and love using managed identity for authenticating to Entra ID protected APIs just as much as I do.
What are Managed identities for Azure resources?
A managed identity allows an Azure-hosted app to access other Entra ID protected services without having to specify explicit credentials for authentication. When you enable the managed identity for your app, a service principal gets created for your application in Entra ID. You can then grant that principal varying levels of permissions to the Azure resources and APIs used by your application. When we do not need to use and store separate credentials, it automatically improves the security of our application.
“When you enable managed identity on your web app, Azure activates a separate token-granting REST service specifically for your app to use. Your app requests tokens from this service instead of directly from Microsoft Entra ID. Your app needs to use a secret to access this service, but that secret is injected into your app’s environment variables by App Service when it starts up. You don’t need to manage or store this secret value anywhere, and nothing outside of your app can access this secret or the managed identity token service endpoint.” [source]
Managed identity is available for many Azure resources, such as Azure Functions, Web Apps and Logic Apps. You can check the Microsoft documentation for a full and up-to-date list of all the resource types that support managed identities.
System assigned vs. User assigned managed identities
We have two different types of managed identities: system assigned and user-assigned. Both of them work pretty much the same way from the authentication perspective, but they are administered quite differently. Being able to make the correct decision between them based on your scenario can help you reduce administrative overhead.
A system-assigned managed identity is always tied to just that one resource where it is enabled. You then control the permissions for that application individually. This is the preferred approach if your apps need different roles for different services.
A user assigned managed identity is created as a separate Azure resource. It can then be given permissions to services and added to multiple different Azure resources. This is the preferred approach if several apps need the same permissions to the same services.
Note that you don’t necessarily need to choose to use just either a system assigned or a user-assigned managed identity. Depending on the Azure resource, you can often combine both and use multiple user-assigned managed identities. You should always follow the principle of least privilege, and plan the permissions of the identities to be as fine-grained as possible.
Enabling the managed identity for your Azure application
You can enable the system managed identity for an Azure resource by going to its Identity blade, changing the Status to On and then hitting Save. After saving, you’ll see a GUID in the Object ID field. This is the ID of the managed service identity. You’ll need the ID for managing your app’s permissions.
Managing your app’s permissions to the API
A widespread approach has been to enable the managed identity so that your app can securely access sensitive information stored in an Azure Key Vault. We’d do this for, e.g., getting a client secret from the key vault for authenticating to Microsoft Graph. However, it is also possible for us to grant our application permissions directly to Microsoft Graph (and other APIs) with PowerShell, which essentially allows us to skip the whole Azure Key Vault step entirely. At the time of this writing, PowerShell is our only option for performing this task; there is no way to do it in the Azure Portal.
Before you run the scripts, replace the managedIdentityId
variable value with the ID of your application’s managed identity. You can see the ID in the view where you enabled the feature.
Also, if you want to manage your application’s permissions to some other API than Microsoft Graph, replace the appId
variable value with the ID of the other API. You can find the ID of the API in the Enterprise applications view in Entra ID. There, select All Applications as the Application type, and search for your API. Then copy the GUID from the Application ID column.
Adding permissions
You can use the following script for granting permissions to an Entra ID protected API for your Azure-hosted app that has its managed identity enabled. Replace the permissions
variable value with the API permissions/roles your application requires.
Checking existing permissions
If you later need to check what permissions your app has to the API in question, you can do that with the following script. You can run this script without the administrator roles mentioned above.
Removing permissions
If your app no longer needs some of the permissions granted earlier, you can remove them individually with the following script.
Authenticating using the managed service identity
Here I have a couple of examples for you on how to use a managed identity for authentication in your solution. First, we have a .NET solution, and then I’ll show you how we can easily call an API in an Azure Logic App, and authenticate to the API with the logic app’s managed identity.
.NET
As the first thing, install the Azure.Identity NuGet package to your project, and specify a matching using statement in your code file: using Azure.Identity;
The code below will get an access token for the specified API using the managed identity of the Azure resource that is running your app. The resourceUrl
should be set to the URL address of the API (e.g., https://graph.microsoft.com
or api://your-api-clientid-guid-here
in the case of a custom API).
Azure Logic Apps
Calling an API in Azure Logic Apps with the HTTP action by using a managed identity is super easy. You first add either a system-assigned or a user-assigned managed identity for your app — just like you would for any other Azure resource. Then, while configuring the HTTP action, you select Managed Identity as the authentication type and select the identity from the dropdown. The only thing that requires a bit of typing regarding authentication is the Audience which is the URL of the API you want to call.
Afterword
So, what do you think of using managed identities for authentication? They are pretty awesome, eh? If you have any thoughts, comments or questions about the topic, feel free to write about them to me using the comments section below. I genuinely hope you enjoyed reading this article and found it useful.
If you’d like to subscribe to my blog to get notified when I publish something new, you can find a button for that in the side bar or at the bottom for mobile.
Thank you for reading, it is always appreciated, and until next time!
Laura
Hi Laura, great information!
I have stuck with below scenario, is there any way out?
We are currently using Azure Logic Apps to pull data from ServiceNow. Initially, we used a Service Principal (Azure AD AppId) with OAuth2.0 authentication. The steps we followed were:
1. Obtained an OAuth2.0 token using ClientID and Client Secret using HTTP Post action
POST
URI :
https://login.microsoftonline.com/{tenanid}/oauth2/v2.0/token
Headers
content-Type:application/x-www-form-urlencoded
Body
grant_type=client_credentials&scope=mysnowscope/.default&client_id=myclientidxyz&client_secret=mycleintsecretxyz
2. Used the token generated from Step1 (bearer token) to authenticate our ServiceNow GET API requests. (HTTP GET Action)
https://mysnowinstance.service-now.com/api/now/table/u_work_activity?sysparm_limit=1001&u_record_restriction=none&sysparm_query_category=API&sysparm_display_value=true
Authorization:@concat(‘Bearer ‘,body(‘Parse_JSON’)?[‘access_token’])
However, due to a new policy, we can no longer use ClientID and Client Secret for authentication.
We are using user assigned managed identity and given read-write access to Managed Identity’s ClientID in ServiceNow.
I tried using user assigned managed identity by Managed Identity as the Authentication Type in HTTP Action. Also given read-write access to MI clientid in ServiceNow.
Is there a way to achieve this using Managed Identity or federated credentials in HTTP Request?
This is resolved by us. The approach followed by us was correct. only difference was audience property. Earlier we were trying with scope parameter value defined by ServcieNow. After removing suffix “./default” API calls started working from Logic Apps using managed identity
Hi, great article. But, how is this in the year 2023? Does is still apply? From what I can find it is also possible for example for a function to have an managed identity and get a bearer token directly from code without app registration.
Hi Antonie,
That is exactly right: Azure Function Apps also have system-assigned managed identities, and those identities can be granted permissions to APIs directly without having to set up an app registration in Entra ID.
Laura
Thanks for the amazing blog! One question – if the ‘session’ remains open with a token lasting 12 hours lets say, what prevents a hijacking attack? Thanks
Great post, thank you. The HTTP connector in Power Automate doesn’t have Managed Identity as an option, do you know if there is any other way to use a Managed Identity for calls to Azure APIs within Power Automate?
thanks
Hi Terry,
Unfortunately, using Managed Identity for Azure Resources is impossible in Power Automate because Power Automate flows are not Azure resources like Azure Logic Apps.
Laura
Hi Laura, great article.
Do you know if its possible to use a managed identity on a Multi Tenant App Registration scenario?? I’d like to use a managed identity to authenticate to graph (my app registration is allow in 5 different tenants) to all those tenants and not have to use a certificate or secret to do that.
Thanks
Hi,
Currently its not supported to have Manage Identity cross directories (Tenants)
FAQ :
https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/managed-identities-faq#can-i-use-a-managed-identity-to-access-a-resource-in-a-different-directorytenant