Secure Plugin Development in Dataverse: Using Managed Identity with Azure Key Vault (No Secrets!)

Kefasi JaravazaKefasi Jaravaza
5 min read

Managing secrets and API keys securely in cloud-based enterprise apps is critical — especially in Dynamics 365 and Power Platform projects where plugins often need to call external APIs. In this post, I’ll walk you through how I implemented Managed Identity with Federated Credentials for a Dataverse Plugin to securely retrieve secrets from Azure Key Vault, removing the need for storing API keys in configuration entities or environment variables.

This setup was essential for my use case — validating phone numbers and email addresses using a third-party external service — but the approach can apply to any plugin needing secure secret access.

Where Can You Store Secrets? (And Why Most Options Are Insecure)

One of the most important decisions when building secure Dynamics 365 and Dataverse plugins is: Where do you store your secrets?

This simple but powerful table shows what many of us have been doing — and why we need a better way:

LocationDescriptionSecurity
Environment Variable (string)Easy to configure but not encrypted❌ Insecure
Plugin Secure ConfigurationAccessible via code, still vulnerable❌ Insecure
Custom config entityStore encrypted values in a table, but still manually handled❌ Insecure
Hardcoded in codeThe worst option – secrets in source control❌ Insecure
Environment Variable (Key Vault)Promising but not usable in plugins (yet)🚫 Not Applicable

💥 Insight: Most of us have been forced to adopt insecure workarounds because Dataverse plugins historically lacked support for secure secret retrieval.


What Changed?

With the GA release of Managed Identity support for Dataverse plugins in March 2025, we now have a secure, modern approach.

🔐 Why Use Managed Identity with Plugins?

Before diving into the technicals, let's explore why you'd use this setup:

  • No secrets in the plugin code

  • No environment variables holding secrets

  • No need for client secrets or certificates

  • Secrets are retrieved securely from Azure Key Vault, using Azure AD tokens via a federated App Registration

🛠️ Step-by-Step Implementation

1. Create an Azure App Registration with Federated Credentials

Use the App Registration as your identity provider instead of a traditional Managed Identity. This is crucial if you're deploying your plugin into a Power Platform environment that supports Federated Credentials.

In your app registration:

  • Go to Certificates & secrets → Federated credentials

  • Set Issuer to your Dataverse STS:

    https://[environment ID prefix].[environment ID suffix].environment.api.powerplatform.com/sts

    Environment ID prefix - The environment ID, except for the last two characters.

    Environment ID suffix - The last two characters of the environment ID.

    Example: https://02e1c0123456789f46a.09.environment.api.powerplatform.com/sts

  • Use a subject in this format: component:pluginassembly,thumbprint:YOUR_CERT_THUMBPRINT},environment:{YOUR_ENV_ID}

  • Set Audience to: api://azureadtokenexchange

2. Create and Sign Your Plugin with a Certificate

Your plugin assembly must be signed with a valid certificate whose thumbprint is referenced in the federated credential.

Here’s a PowerShell snippet to create and export the certificate:
$cert = New-SelfSignedCertificate ` -Subject "CN=PluginCert" ` -CertStoreLocation "Cert:\\CurrentUser\\My" ` -Type CodeSigningCert ` -KeyExportPolicy Exportable ` -KeySpec Signature ` -KeyLength 2048 ` -HashAlgorithm SHA256 $pwd = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText Export-PfxCertificate -Cert "Cert:\\CurrentUser\\My\$($cert.Thumbprint)" -FilePath "C:\\Temp\\PluginCert.pfx" -Password $pwd

Get your thumbprint using powershell:

Export to PFX

$pwd = ConvertTo-SecureString -String "Clarion" -Force -AsPlainText

Export-PfxCertificate -Cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" -FilePath "C:\Temp\LoqatePluginCert.pfx" -Password $pwd

Then sign the DLL: signtool sign /fd SHA256 /f "C:\Temp\PluginCert.pfx" /p YourPassword "Path\To\Plugin.dll"

Example: signtool sign /fd SHA256 /f "C:\Temp\LoqatePluginCert.pfx" /p yourpass "C:\Users\KJaravaza\source\repos\EmailValidation\bin\Debug\EmailValidation.dll"

3. Register and Deploy the Plugin

Deploy the signed plugin assembly into Dataverse using standard methods (Plugin Registration Tool, Power Platform CLI, or DevOps pipelines).

Then link the plugin to your federated identity using a PATCH request:

PATCH /api/data/v9.2/pluginassemblies({pluginAssemblyId})
{
    "managedidentityid@odata.bind": "/managedidentities({managedIdentityId})" 
}

🔐 Set Up Azure Key Vault

Create your Key Vault and store the API secret (e.g., Loqate API key) under a name like LoqateAPIKey.

Assign Roles

Your App Registration needs:

  • Key Vault Secrets User

  • Key Vault Reader (sometimes needed for specific scenarios)

Use the Azure Portal or CLI to assign these roles.

Key Vault Access Policies (Alternative to RBAC)

In some setups — especially if Access Policies are enabled instead of RBAC — you'll also need to add your App Registration explicitly to the access policies list in Key Vault.

Steps (in the Azure Portal)

  1. Go to your Key Vault

  2. Select Access policies

  3. Click + Add Access Policy

  4. Grant Get and List permissions under Secret Permissions

  5. Under Principal, select your App Registration

  6. Save the changes

📝 Microsoft is shifting towards RBAC-only access for Key Vault, but some environments still require Access Policies. Check which model your vault is using before proceeding.

Sample Code Snippet

Here’s a simplified plugin method to securely access secrets from Key Vault:

var managedIdentityService = (IManagedIdentityService)serviceProvider.GetService(typeof(IManagedIdentityService));
var token = managedIdentityService.AcquireToken(new[] { "https://vault.azure.net/.default" });

using (var httpClient = new HttpClient())
{
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    var response = await httpClient.GetStringAsync("https://your-kv.vault.azure.net/secrets/APIKey?api-version=7.3");
    dynamic result = JsonConvert.DeserializeObject(response);
    string apiKey = result?.value;
}

Final Thoughts & Recommendations

Now that I’ve successfully implemented Managed Identity in a real-world plugin, here are a few things I learned (and wish I knew sooner):

  • Federated credentials are the way forward for secure, scalable plugin deployments.

  • Federated identity setup is strict — your issuer, subject, and audience must match exactly.

  • Trace logs help — but be careful not to expose secrets. Strip out API keys from traces.

  • Access Policy vs RBAC — understand what your Key Vault is configured to use. your plugin with a certificate and use its thumbprint in federated identity setup.

📚 Resources

0
Subscribe to my newsletter

Read articles from Kefasi Jaravaza directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kefasi Jaravaza
Kefasi Jaravaza