Start here — core concepts
The foundational ideas in plain language.
A managed identity is an identity in Microsoft Entra ID that represents your application or workload, and whose credentials Microsoft manages for you behind the scenes. Your code never sees or handles those credentials — it just says “I am this identity,” Entra ID confirms it, and the resource you’re calling trusts that confirmation. For Power Platform, it lets a Dataverse plug-in get an access token to call Azure resources without storing any password or secret.
The problem of stored credentials. Traditionally a plug-in that needed to call a protected resource had to carry a secret (a client secret or password). Secrets leak, expire, need rotating, and widen your attack surface. Managed identity removes the stored secret completely: a trusted authority vouches for the plug-in’s identity instead, so there is no secret to protect.
A client secret is essentially a password for an application. To authenticate, the secret must be present wherever the code runs. That creates risk: anyone who can read the config, the code, or a log can copy it and impersonate your app; it has an expiry date that breaks your integration when it passes; and every stored copy is one more thing an attacker can target. Managed identity exists specifically to eliminate this stored secret.
Microsoft Entra ID (formerly Azure Active Directory / Azure AD) is Microsoft’s cloud identity service. It’s the “who’s who” directory that issues and validates tokens for users and applications across Microsoft 365, Azure, and Power Platform. In this scenario it’s the trusted authority that issues your plug-in’s token.
An app registration is how you tell Entra ID that an application exists and define its identity (client ID), permissions, and how it can authenticate. In this setup, the app registration is the identity your plug-in presents. You can apply Azure policies to it and reference it by its appid.
When an app registration is used within a specific tenant, Entra ID creates a service principal — the local instance of that app identity that actually gets permissions and roles assigned. Loosely: the app registration is the global definition; the service principal is its presence in your directory that you grant access to.
An access token is a short-lived, signed digital pass (a JWT) that proves the caller’s identity and what it’s allowed to access. Your plug-in gets one from Entra ID and presents it (as a Bearer token) to the resource. The resource checks the token’s claims and grants access. Tokens typically expire within about an hour and are requested fresh on demand.
OAuth is the industry-standard protocol for issuing and validating access tokens so one system can securely access another on a defined scope, without sharing passwords. “Securing a flow with OAuth” means the flow demands a valid Entra ID token and checks its claims before running.
It means no long-lived secret (password/client secret/key) is stored in your plug-in, its configuration, or your code. The plug-in proves its identity through a federated trust anchored to its signing certificate, and the platform hands it a short-lived token on demand. There is no static secret sitting at runtime to be stolen.
Setting it up involves a code plug-in (pro-code) plus configuration steps that a maker/admin can do (solution, environment variable, flow, Custom API). Once it’s built and published, a low-code maker can call the resulting Custom API from a flow or app without touching credentials. So: pro-dev builds it once; makers consume it safely thereafter.
Architecture — how the pieces connect
Federated credentials, the Dataverse record, the certificate, and the runtime flow.
A federated identity credential is a trust rule attached to your app registration. It says: “Entra ID, accept a token request where the issuer is this and the subject describes this exact workload — and in return, issue an access token for this app.” It replaces a stored secret with trust based on identity. For plug-ins, the subject encodes the tenant, the environment, the plug-in, and the signing certificate.
It’s the broader mechanism behind the FIC: letting a non-Microsoft or platform workload prove its identity to Entra ID using a signed assertion from a trusted issuer, instead of a secret. The same idea lets GitHub Actions and Kubernetes authenticate to Azure without secrets. Power Platform uses it so a plug-in can get a token without holding a credential.
Five pieces work together:
- App registration (Entra ID) — the identity.
- Federated credential (on the app) — the secret-free trust rule.
- Signing certificate — the plug-in’s fingerprint, referenced by the FIC.
- Managed identity record (in Dataverse) — the local pointer to the Azure identity, attached to the plug-in assembly.
- The plug-in — signed code that calls
AcquireTokenand uses the token to reach the resource (Key Vault, your API, a secured flow).
Chain of trust: the certificate proves the plug-in → the FIC trusts that identity → Entra ID issues a token → the resource trusts Entra’s token.
Dataverse and Entra ID are separate systems. The managed identity record (in the managedidentities table) is Dataverse’s local pointer to your Azure identity — it stores the client ID and tenant ID. You then attach it to your plug-in assembly. The plug-in code never names an identity, so this record is how Dataverse knows which Azure identity to request a token for when the plug-in calls AcquireToken.
Issuer — who is allowed to issue the assertion (your tenant’s issuer URL). Subject — the exact identity string describing the workload (tenant + environment + plug-in + certificate). Audience — who the assertion is intended for (for public cloud, api://AzureADTokenExchange). Entra ID issues a token only when an incoming request matches all three.
The FIC subject includes the environment ID, so the trust is scoped to one Power Platform environment. That’s why moving to production requires adding a new FIC for the production environment ID — the certificate and app stay the same, but the environment-specific pieces are redone.
The certificate is the plug-in’s verifiable fingerprint. The FIC subject includes the certificate’s hash (self-signed) or issuer+subject (CA cert). At deployment, the platform verifies the assembly was signed by that certificate before it will produce an assertion. So even a copied plug-in can’t impersonate yours without being signed by the same certificate.
1) The plug-in fires and calls AcquireToken(scopes). 2) The Power Platform runtime builds a signed assertion proving the plug-in’s identity (cert + environment). 3) Entra ID validates that assertion against the federated credential and issues a short-lived access token. 4) The plug-in presents the token to the resource (e.g. a secured flow). 5) The resource validates the token’s claims and responds. No secret was stored or transmitted anywhere.
It’s the service your plug-in requests from the sandbox to get a token. The method signature is string AcquireToken(IEnumerable<string> scopes). You pass the scope(s) for the resource you want (e.g. Key Vault, your API), and it returns an access token — handling the entire federated acquisition for you, with no credentials in your code.
There are actually two different checks, by two different parties, on two different things — they’re easy to mix up:
- Check 1 — Dataverse / Power Platform (this is the asymmetric-key one). The certificate’s private key signs the DLL; the public key verifies that signature. Power Platform uses the public key to confirm “this plug-in really was signed by that certificate and hasn’t been tampered with.” Azure is not involved here — it never even receives your DLL.
- Check 2 — Azure (Entra ID), but it checks something else. Azure does not re-check your code signature. When the plug-in asks for a token, Power Platform sends Azure a small signed statement (the assertion) meaning “this request comes from the plug-in signed by certificate #ABC123, in environment X.” Azure then (a) verifies that statement’s signature using Power Platform’s public keys, and (b) checks that the fingerprint and environment in it match what you registered in the federated credential.
So: Dataverse verifies the plug-in (with the public key); Azure verifies Power Platform’s signed statement and matches the fingerprint — never the code, never the private key.
Think of your signature as a wax seal on a letter. Dataverse is the mailroom that checks the wax seal against your stamp to confirm the letter is genuinely yours and unopened — the public-key verification. Azure is the bank. The bank doesn’t re-examine the seal; the mailroom hands it a signed note (“this came from the holder of seal #ABC123, at branch X”). The bank confirms the note is really from the mailroom it trusts, and that the seal and branch are on its approved list — then it pays out (issues the token). The bank trusts the mailroom’s word plus the fingerprint on file; it never needs the seal itself.
Certificates & signing
Self-signed vs CA, why signing matters, the timestamp, expiry, and reuse.
Code signing applies a cryptographic signature to a file (your DLL) using a certificate’s private key. It proves two things: who published the code (authenticity) and that it hasn’t been altered since (integrity). In this scenario it also anchors the managed-identity trust — the signature ties the assembly to the certificate the FIC trusts.
A certificate you create yourself, signed by your own key rather than by a recognized authority. It’s free and instant, and works fine for development and testing. But nobody outside your machine inherently trusts it, so Microsoft does not recommend it for production.
A certificate issued by a recognized Certificate Authority (CA) such as DigiCert, Sectigo, or GlobalSign, after they verify your organization’s identity. Because the CA is widely trusted, the certificate carries that trust. For production code signing you buy a Code Signing certificate from such a CA.
| Self-signed | CA-issued | |
|---|---|---|
| Cost | Free | Paid (annual) |
| Trust | Only where you install it | Broadly trusted |
| Identity verified? | No | Yes (CA validates your org) |
| Use for | Dev / test only | Production |
| FIC subject format | Uses the cert hash (/h/) | Uses issuer + subject (/i/…/s/…) |
Rule of thumb: prototype with self-signed, ship to production with a CA certificate.
Because the signature is what makes the plug-in’s identity verifiable. The federated trust is anchored to the certificate; without a matching signature, Entra ID won’t recognize the plug-in and token acquisition fails. Signing is what turns “some code” into “code with a provable identity.”
Yes. Each rebuild produces a fresh DLL that has the strong name but not the certificate signature — the previous signature is gone with the old file. So the routine is always: build → re-sign with the same certificate → update the assembly in Dataverse. Tip: add the signing command as a Visual Studio post-build event so it happens automatically.
Unlimited. One certificate can sign any number of plug-ins (and other artifacts). You never need a separate certificate per plug-in. The only per-plug-in piece is the federated credential in Entra ID, and even that references the same certificate’s hash.
It’s a free, trusted timestamp service. When you sign, the tool asks it for the official current date and stamps it onto the signature. This changes the validation rule to “valid as long as the certificate was valid at the moment of signing” — so the signature survives the certificate’s expiry. Like a notary dating a document: years later, even if your ID expired, the dated stamp proves you signed it while valid. Internet is needed only at signing time; the date is then baked into the file. The DigiCert URL isn’t special — any RFC 3161 timestamp server works (e.g. Sectigo’s).
If you signed with a timestamp, an already-signed and registered plug-in keeps working past expiry — no action needed. If you signed without a timestamp, it becomes untrusted at expiry. And to sign a brand-new build after expiry, you must renew the certificate and update the FIC hash. So: timestamp your signatures, and renew the cert when you next need to build.
A .pfx contains the private key (and is password-protected) — it’s what you sign with. A .cer is the public certificate only (no private key) — it’s safe to share, and its hash is what goes into the federated credential. Keep the .pfx protected; the .cer is not sensitive.
The federated credential subject uses the SHA-256 hash of the .cer (from Get-FileHash … SHA256, lowercase, no spaces). The “Thumbprint” shown in the Windows cert dialog is SHA-1 — a different value. Don’t use the dialog thumbprint for the FIC.
The password is whatever you choose in the Export-PfxCertificate -Password step — it’s not generated for you. Store it somewhere safe (a password manager or Azure Key Vault). You’ll need the same password whenever you sign from the .pfx again (e.g. on a build server). On the machine that created the cert, you can sign from the certificate store with no password at all.
The Subject labels — the common name (CN=YourCompany) and email — are free to set to your organization; they’re just display names and needn’t be real. Leave the technical bits (Code Signing usage, RSA, key length) as-is, since those are what make it able to sign. Note: changing the cert itself (re-creating it) changes its hash, which means updating the FIC.
EKU defines what a certificate is allowed to do. The OID 1.3.6.1.5.5.7.3.3 is Code Signing; 1.3.6.1.5.5.7.3.4 is Secure Email. A common pitfall: Microsoft’s sample snippet creates a Secure-Email-only cert, which SignTool rejects with “No certificates were found that met all the given criteria.” The fix is to include the Code Signing usage when creating the cert.
A certificate makes a claim: “this software was published by [Your Company].” The whole difference is who confirms that claim.
Self-signed — you confirm your own claim. It effectively says “this is from My Company, and the proof is… My Company says so.” That’s circular — no independent party. Anyone could generate a cert that says the same thing. It proves the file wasn’t tampered with, but not reliably who made it.
CA-issued — a trusted authority (DigiCert, Sectigo, GlobalSign) verifies your organization’s identity before signing your cert. Now the claim is backed by a neutral party everyone already trusts.
The technology is identical (private key signs, public key verifies); the only difference is trust: self-signed trust comes from you; CA trust comes from an authority everyone already believes. Analogy: self-signed is a handwritten note saying “I am John Smith”; CA-issued is a passport — a recognized authority checked you, so strangers accept it.
Trust isn’t a property of the certificate — it’s about whose Trusted Root list the certificate (or its issuer) is on. Windows, Azure, and browsers ship pre-loaded with the big public CAs. When you generated a self-signed cert, it was placed in your machine’s own store, so only your machine trusts it. No other computer has it on its list, and no authority it already trusts vouches for it — so elsewhere it’s “untrusted.” A CA cert is trusted everywhere because the CA is already on everyone’s list. (Analogy: a home-printed VIP pass works in your house; an official ticket works at every gate.)
Nuance for this setup: the managed-identity token flow trusts your plug-in by fingerprint match in the federated credential, not by the OS root store — which is why a self-signed cert still functions here.
The signing math is equally strong — “CA is more secure” is misleading. The real gaps are about what an attacker can get away with:
- Impersonation: anyone can generate a self-signed cert that says
CN=YourCompanyin seconds; nothing distinguishes it from yours. A CA refuses to issue “YourCompany” to someone who isn’t you. - No revocation (the big one): if a self-signed key leaks, there’s no kill switch — no authority to publish “this cert is now bad.” A CA can revoke it, and revocation-checking systems then reject anything signed with it.
- Uncontrolled trust: installing a self-signed cert into a machine’s Trusted Root makes it trust anything that cert ever signs, forever, with no clean way to pull it back.
- No accountability: a CA cert ties the signature to a legally verified org; self-signed ties it to “whoever generated it.”
Nuance for this setup: because Azure matches a registered fingerprint (not a CA or revocation list), the impersonation and trusted-store gaps are softened — a look-alike won’t match your hash. But revocation, accountability, and governance still bite in production: a leaked self-signed key has no kill switch, tends to live un-managed on a laptop, and won’t pass a security/compliance review. So the honest case for CA in production is “unmanageable and unrevocable when something goes wrong” — not “weaker encryption.”
In development you’re the only one who needs to trust the cert — so self-signed is fine and free. In production the certificate becomes the anchor of “this plug-in is genuinely ours,” and others depend on that: identity must be real (not self-declared and forgeable), it must be governable and revocable if compromised, and it must pass audit/compliance — reviewers expect a recognized CA because that’s the only signature an outside party can independently verify. Microsoft’s own guidance: self-signed for testing, CA-issued for production.
What matters is the certificate file (the .pfx, with its private key and password) — not the specific computer. Azure matches the fingerprint, so you can sign from any machine that has the .pfx.
- Different machine: works — import the
.pfx(or sign directly from it withsigntool /f MyCert.pfx /p …). - Machine destroyed,
.pfxbacked up: no problem — restore it elsewhere. Already-deployed plug-ins never notice. - Machine destroyed, cert never exported: the private key is lost. Deployed plug-ins keep running (if timestamped), but to ship a new build you must create a new cert, update the federated credential’s hash, re-sign, and re-deploy.
So back up the .pfx and its password somewhere shared (password manager, or ideally Azure Key Vault), and treat the signing cert as a team asset — not something living on one laptop.
You’re right that for an already-deployed, timestamped plug-in the expiry date doesn’t matter — the timestamp froze its trust at signing time, so it keeps running indefinitely. Expiry only matters in three moments:
- Your next rebuild: you cannot create a new signature with an expired cert, so the next time a developer rebuilds the DLL they need a valid cert again.
- Any signature made without a timestamp: that one does become untrusted at expiry.
- Re-signing: a new cert means a new fingerprint, which triggers the federated-credential update.
So expiry isn’t a time bomb on running code — it’s a “renew before your next build” reminder. (Like a driver’s licence: an old signed contract stays valid, but you can’t sign a new one with an expired licence.) Tip: give self-signed dev certs a longer validity (e.g. 3–5 years) to hit this less often.
The deciding question is always: did the fingerprint (hash) change? New fingerprint → you must update the federated credential; same fingerprint → no Azure change.
Self-signed: regenerating always produces a new key pair → new fingerprint, so you always update Azure. Steps: (1) create a new self-signed cert; (2) get the new hash with Get-FileHash MyCert.cer -Algorithm SHA256; (3) update the federated credential’s /h/{hash} in the app registration; (4) re-sign with timestamp; (5) update the assembly in Dataverse.
CA-issued: if it’s renewed with a new key, do the same update — but if the federated credential was set up by issuer + subject (not raw hash) and you stay with the same CA/org, it may keep matching with no Azure change. Some CAs also renew keeping the same key → same fingerprint → nothing to update. Either way you re-sign and re-deploy. In all cases, already-deployed timestamped plug-ins stay up throughout.
Security deep-dive
Why this is safer, what to protect, and how the private key differs from a secret.
It is sensitive, but it’s fundamentally safer than a client secret for two reasons:
- Where it’s used. A client secret must be present at runtime, wherever the code authenticates — so it’s deployed and exposed to anything that can read that location. The certificate’s private key is used only at signing time, on your build machine. It is never deployed with the plug-in and never used by the running plug-in. At runtime the plug-in holds no credential at all.
- How it’s stored. The private key lives in the Windows certificate store with proper access controls — or, for production, in an HSM/hardware token (EV certs) — not in a config file or code.
So you protect one key in one controlled place (signing), instead of scattering a secret across every runtime environment.
Because there is no long-lived secret at runtime to steal. The plug-in authenticates through federation and receives a short-lived, resource-scoped token on demand. Even if a token were intercepted, it expires quickly and only works for one resource. With a client secret, a single leak gives an attacker durable, reusable access.
No. The private key stays in the certificate store (or HSM) on the signing machine. The deployed plug-in DLL carries only the signature (and the public certificate), not the private key. At runtime the plug-in never touches the key — the platform handles identity via federation.
Mainly the signing private key (the .pfx / cert store entry) and its password. Protect the build/signing environment, restrict who can sign, and for production use a CA cert with key protection (HSM). Everything else — the public cert, its hash, the app’s client/tenant IDs — is not sensitive. There’s no runtime secret to guard.
Tokens are short-lived (typically ~1 hour), scoped to a single resource, and acquired on demand — so the window and blast radius are small. Always call resources over HTTPS so tokens aren’t exposed in transit. Compared to a static secret, a token is a far less attractive target.
An attacker with the private key could sign code as you — but to actually impersonate your plug-in they would also need a matching federated credential and managed identity record in your environment, which is defense in depth. Response: revoke/replace the certificate, update the FIC to the new cert hash, re-sign and re-deploy, and (for CA certs) report the compromise to the CA. Storing the key in an HSM greatly reduces this risk.
Every stored secret is a target. By removing the secret entirely, you remove that target — no secret in configs, code, logs, or backups to leak; nothing to rotate and accidentally mishandle. The remaining sensitive item (the signing key) is isolated to one controlled place.
Yes. Identity-based access is centrally visible in Entra ID, you can apply Azure policies to the app identity, and there are no secrets sprawled across environments to inventory or rotate. That makes access easier to audit, attribute, and govern than secret-based access.
Operations & lifecycle
Building, renewing, and promoting across environments.
Yes — every rebuild overwrites the DLL and removes the signature. Always build → re-sign with the same certificate → update the assembly. Automate it with a post-build event so you can’t forget.
Create/obtain a new certificate, update the federated credential’s subject to the new cert’s hash (self-signed) or issuer/subject (CA), re-sign the assembly with the new cert, and re-deploy. Already-signed-and-timestamped builds keep working until you rebuild. Plan renewals ahead of the certificate’s expiry date.
The certificate, signed plug-in, and app registration are reused. The per-environment pieces are redone in production: add a new federated credential with the production environment ID, recreate the managed identity record + link in the prod environment, and set the production flow’s URL in the environment variable. Rule of thumb: anything tied to the environment ID is per-environment; anything tied to the cert or app is shared.
Yes. One app registration can back multiple plug-ins, and you add a separate federated credential entry for each plug-in/environment combination — all on the same app, all referencing the same certificate. This keeps identity management centralized.
Remove or disable the federated credential on the app registration (so Entra stops issuing tokens for that workload), and/or remove the resource permission/RBAC the app had. You can also detach the managed identity record from the assembly in Dataverse. Because access is identity-based, revocation is centralized — no secret to chase down.
Managed identity for Dataverse plug-ins (including dependent assembly plug-ins) is generally available and Microsoft-supported. Availability details for specialized clouds and the latest support boundaries are in Microsoft’s documentation — verify there for your specific cloud and region.
When you need a fresh cert (typically at the next rebuild after expiry):
- 1. Get a valid cert — self-signed: regenerate (new key/hash); CA: renew/reissue.
- 2. Get the new fingerprint:
Get-FileHash MyCert.cer -Algorithm SHA256. - 3. Update the federated credential in the app registration if the fingerprint (or issuer/subject) changed.
- 4. Re-sign the DLL with a timestamp (
/t http://timestamp.digicert.com). - 5. Update the assembly in Dataverse, and back up the new
.pfx+ password.
Deployed, timestamped plug-ins stay up throughout — this work is only needed to ship the next build. Tip: renew a couple of weeks before expiry so it’s planned, not a scramble.
Cost & business value (for stakeholders)
What it costs, what it saves, and the risk of the status quo.
There’s no separate license fee for the managed identity capability itself — it’s part of your existing Power Platform/Dataverse and Azure setup. App registrations in Entra ID are free, and a user-assigned managed identity has no charge for the identity itself (you only pay for the Azure resources it accesses). The one real cost for production is a CA code-signing certificate (see below). For most teams the feature is effectively free; the certificate is the line item.
Roughly US$200–$700 per year, depending on the CA and type. Standard (OV) code-signing certificates are at the lower end; Extended Validation (EV) certificates cost more and usually require a hardware token (HSM). Prices and offerings change over time and by vendor, so confirm with the CA (DigiCert, Sectigo, GlobalSign, etc.). Because one certificate signs many things, the effective per-project cost is low.
Stored secrets carry ongoing cost and risk: breach exposure (a leaked secret can grant durable access), operational toil and outages (secrets expire and must be rotated, often causing downtime when missed), compliance findings (auditors flag secrets in configs/code), and incident cost if one leaks. Managed identity removes the asset that drives all of these.
Lower breach risk (no secret to steal), less operational overhead (nothing to rotate), cleaner audits and compliance posture, and a modern, standards-based security model that scales across teams. The investment is small (a certificate plus one-time setup); the saving is the recurring cost and risk of secret management.
A code-signing certificate isn’t tied to this plug-in or even to Dataverse. The same certificate can sign: other Dataverse plug-ins and plug-in packages, any .NET assemblies (.dll/.exe), MSI/installers, PowerShell scripts & modules, NuGet packages, ClickOnce apps, Office VBA macros, and (with an EV cert) Windows drivers. So one purchase can cover code-signing needs across many teams and projects — which is why the per-use cost is so low.
Typically: an Entra ID / Azure admin (to create the app registration, federated credential, and grant admin consent), a pro-code developer (to build and sign the plug-in), a Power Platform admin/maker (solution, flow, Custom API, managed identity record), and your security team (to approve the certificate and consent). It’s a one-time collaboration; ongoing operation needs little.
Many frameworks discourage long-lived secrets in code/config and require strong access governance. Eliminating stored secrets and using centrally-managed, auditable identities aligns with those expectations and reduces audit friction. Confirm specifics with your compliance team for your regulatory context.
Comparisons & decisions
How it stacks up against the alternatives, and when to choose what.
| Approach | Secret at runtime? | Best for |
|---|---|---|
| Client secret | Yes (must be stored) | Quick demos; legacy — least secure |
| Certificate credential | Key must be available to authenticate | Stronger than a secret, but still key management |
| Managed identity | No | Recommended — credential-free, least to manage |
Managed identity is the strongest of the three because there is no long-lived credential present where the code runs.
They solve different things and pair well. Key Vault stores secrets/keys; managed identity is how you authenticate to retrieve them without a secret. A classic pattern: the plug-in uses managed identity to authenticate to Key Vault and fetch a secret it needs — so even when a secret is unavoidable, you never store that credential in the plug-in.
Choose an app registration when you want an app identity you can govern with Azure policies and reference by appid. Choose a UAMI when you want a standalone service principal to assign RBAC to a resource. Both work for plug-in managed identity; app registration is common when you need app-level governance.
When the resource you’re calling doesn’t support Entra ID authentication (e.g. a third-party API that only accepts a static API key) — there’s no token for it to validate. In that case, store the key in Key Vault and use managed identity to retrieve it, so the key still isn’t embedded in your plug-in.
Pro-developer & advanced
Scopes, clouds, packaging, and common errors.
Any resource that supports Entra ID authentication and that your app is permitted to access — for example Azure Key Vault (https://vault.azure.net/.default), your own Web API (api://<client-id>/.default), Azure Storage, Microsoft Graph (where permitted), or Power Automate. You request the appropriate scope when calling AcquireToken, and the resource must be set up to trust/accept that token.
Beyond public cloud, specialized clouds are supported with their own audience, issuer, and subject-prefix values — GCC High & DoD, China (Mooncake), US National (USNAT), and US Secure (USSec). The audience value is case-sensitive and must match exactly. Use the values from Microsoft’s documentation for your specific cloud.
A plug-in assembly is a single signed DLL. A plug-in package is a NuGet package that can bundle an assembly plus its dependencies. Both can be associated with a managed identity; you sign the assembly with SignTool, or sign the package with the NuGet Sign CLI. Use a package when you have dependent assemblies.
AADSTS700213 (no matching federated identity record)— FIC subject/hash mismatch. Copy the expected subject from the error stack into the FIC.AADSTS500011 (resource principal not found)— the audience isn’t known/consented for your app. Expose the API or grant the right permission, and use a matching scope.MisMatchingOAuthClaims(flow 403) — the secured trigger’s claims don’t match the token. Add theaudclaim, grant the Power Automate permission, and align the scope.IManagedIdentityService unavailable— the managed identity record isn’t attached to the assembly. Re-link it.No certificates were found…— the cert lacks Code Signing usage. Recreate it with the correct EKU.
Plug-ins run in the Dataverse sandbox (isolation mode), which restricts certain operations. Outbound HTTPS calls are allowed, so calling a flow or Azure resource works, but you can’t rely on machine-local state, the file system, or some lower-level APIs. Keep token acquisition and HTTP calls within the supported patterns, and use the tracing service for diagnostics.