Connecting to Dataverse from Function App using Managed Identity

EDIT (19-Nov-21): Getting token through Azure Identity SDK means caching has to be handled in the Function App as well (refer https://github.com/microsoft/PowerPlatform-DataverseServiceClient/issues/161#issuecomment-912870265). So, I have slightly refactored the Function App to use caching.

Everyone hates passwords. But, passwords are easy, because most people use the same password across multiple services. When PowerPlatform DataverseServiceClient was first released, everyone were excited, because you can use it with v3 runtime. But at the same time, there was no option to use username, password like you would with CrmServiceClient. So, the next easiest option was to go with AppId and Secret or certificate, if you want bit more security. The only problem is both secrets and certificates expire. When they expire it creates a big headache, especially in integration scenarios.

Meme about Azure AD, Function App and authentication. Iron Man 2
Iron Man 2 featuring Azure AD, Power Apps and Function App

So, now look at a better option – Connecting to Dataverse using Managed Identity. If you would rather read the code than this post, you can head to https://github.com/rajyraman/PowerApps-Managed-Identity-Demo-Functions. You can provision the Function App and associated resources to your Azure tenant by clicking the “Deploy the Azure” button on the repo. After this you need to deploy the Function App and create the Application User in Power Apps.

I have also simplified the process with a Power Shell script that you can run from deploy/run.ps1. This Power Shell script provisions the required Azure resources, deploys the Function App, and also creates the Function App Service Principal as an Application User in your Power Apps environment.

This is where the magic happens.

Getting Token using Managed Identity with Azure Identity SDK
Getting Token using Managed Identity

Three key things in this code:

  1. Token is retrieved transparently using the Managed Identity
  2. Service Client uses the Azure Identity SDK’s GetTokenAsync to get the token. This token is uses on all subsequent calls to Dataverse Web API
  3. We don’t mention a specific scope. So, the scope URI ends with .default

DefaultAzureCredential class figures out the credentials in the following order.

  1. EnvironmentCredential
  2. ManagedIdentityCredential
  3. SharedTokenCacheCredential
  4. VisualStudioCredential
  5. VisualStudioCodeCredential
  6. AzureCliCredential
  7. AzurePowerShellCredential
  8. InteractiveBrowserCredential

Since I launch Azure Function Core Tools from Visual Studio, it will use the credentials I specified in Visual Studio.

Azure Service Authentication on Visual Studio
Visual Studio Azure Account

We are using Azure.Identity to connect to Azure AD. When you run this Function App locally it will use the credentials you used in Visual Studio or Visual Studio Code, or the credentials you used to login in Azure CLI, but when this line runs on the live Function App, it will use the Managed Identity of the Function App. Function App is an Application User in Power Apps with a security role.

Function App shown as Application User in Power Apps
Function App as an Application User

We can also confirm that the Function App is running with Managed Identity (System Assigned).

Function App's Managed Identity on Azure Portal
Function App Managed Identity

The Function App also has Open API attributes (provided by Azure Function Open API Extension), so I can use Swagger UI to interact with the Functions. I love this new capability.

Swagger UI for Function App
Swagger UI

I hope this makes your life simpler when using Azure Functions to connect to Power Apps Web API.

Repo:

https://github.com/rajyraman/PowerApps-Managed-Identity-Demo-Functions

Credits:

  1. This post would not be possible without the conversation I had with Amrit last Friday, where he casually mentioned this idea. Before that, I was always confused how the end to end process will work without AppId or Certification. The article he pointed to me was https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=dotnet#asal. This uses Microsoft.Azure.Services.AppAuthentication package which is deprecated. So, I have switched to Azure Identity. Huge thanks to Amrit. You can follow him on @amritsidhu61 (Twitter) or https://www.linkedin.com/in/sidhuamrit
  2. Justin Yoo – For helping me sort through the Open API issues. You can follow him at https://twitter.com/justinchronicle?s=20