<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anton Staykov</title>
    <description>The latest articles on DEV Community by Anton Staykov (@astaykov).</description>
    <link>https://dev.to/astaykov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3827606%2Fbb3aa4b8-90b5-4db5-8ad5-f9bd05ab762b.jpg</url>
      <title>DEV Community: Anton Staykov</title>
      <link>https://dev.to/astaykov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/astaykov"/>
    <language>en</language>
    <item>
      <title>Enterprise architects: your overdue Entra decision is an agent CSA schema</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Thu, 23 Jul 2026 09:23:00 +0000</pubDate>
      <link>https://dev.to/astaykov/enterprise-architects-your-overdue-entra-decision-is-an-agent-csa-schema-2j5n</link>
      <guid>https://dev.to/astaykov/enterprise-architects-your-overdue-entra-decision-is-an-agent-csa-schema-2j5n</guid>
      <description>&lt;p&gt;If you are an enterprise architect working on Microsoft Entra and AI agents, your first overdue job is not another policy wizard, another dashboard, or another governance steering committee. It is schema design.&lt;/p&gt;

&lt;p&gt;Specifically, it is deciding how you classify non-human identities with &lt;a href="https://learn.microsoft.com/entra/fundamentals/custom-security-attributes-overview" rel="noopener noreferrer"&gt;custom security attributes in Microsoft Entra&lt;/a&gt;. Not eventually. Up front.&lt;/p&gt;

&lt;p&gt;I keep seeing the same pattern across customers of every size: teams move quickly on agent experimentation, they onboard identities, they test controls, and then they realize they have no consistent attribute language for policy scope. At that point, every policy becomes a naming convention problem in disguise.&lt;/p&gt;

&lt;p&gt;That is backwards.&lt;/p&gt;

&lt;h2&gt;
  
  
  The control plane starts with classification
&lt;/h2&gt;

&lt;p&gt;Custom security attributes are not decorative metadata. They are tenant-scoped key-value classifications you can assign to users, enterprise applications (service principals), and agent identities that are modeled as a service principal subtype, with dedicated role and permission boundaries for who can define and assign them (&lt;a href="https://learn.microsoft.com/entra/fundamentals/custom-security-attributes-overview" rel="noopener noreferrer"&gt;overview&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/graph/api/resources/custom-security-attributes-overview?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Graph model&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/entra/agent-id/agent-service-principals" rel="noopener noreferrer"&gt;agent identity service principal model&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That alone should change how architects think about them. This is not "nice to have taxonomy." This is policy input.&lt;/p&gt;

&lt;p&gt;Microsoft Entra Conditional Access for agents supports attribute-driven targeting with custom security attributes, and policy evaluation happens during token issuance and refresh, not just at policy authoring time (&lt;a href="https://learn.microsoft.com/en-us/entra/identity/conditional-access/agent-id#attribute-driven-conditional-access" rel="noopener noreferrer"&gt;Conditional Access for agents&lt;/a&gt;). In other words: if your classification is sloppy, your runtime decisions are sloppy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why agents raise the stakes
&lt;/h2&gt;

&lt;p&gt;You can say "an agent identity is still a service principal" and be technically correct. Microsoft Entra Agent ID is built on service principal infrastructure (&lt;a href="https://learn.microsoft.com/entra/agent-id/agent-service-principals" rel="noopener noreferrer"&gt;agent identities, service principals, and applications&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You can also miss the point.&lt;/p&gt;

&lt;p&gt;Agent identity introduces a blueprint-centered model where one blueprint can represent many agents, where blueprint-level policy decisions can affect all derived identities, and where operational accountability (owners and sponsors) is part of the model (&lt;a href="https://learn.microsoft.com/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;key concepts&lt;/a&gt;). This is not how most architects historically modeled "traditional" workload identities.&lt;/p&gt;

&lt;p&gt;So yes, same substrate. Different operating semantics.&lt;/p&gt;

&lt;p&gt;That difference is exactly why CSA strategy for agents should be deliberate, not inherited by accident from old workload identity templates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reuse your existing workload schema or create a dedicated agent schema?
&lt;/h2&gt;

&lt;p&gt;This is the question every architecture board eventually reaches.&lt;/p&gt;

&lt;p&gt;The honest answer is conditional, not ideological.&lt;/p&gt;

&lt;p&gt;Reusing your existing workload schema has real advantages. It accelerates rollout, avoids duplicate governance machinery, and can be enough if your workload identity estate is already cleanly governed and your agent population is still limited.&lt;/p&gt;

&lt;p&gt;But here is the trade-off many teams underestimate: semantic collision.&lt;/p&gt;

&lt;p&gt;When the same attribute family has to describe static daemon services, integration apps, and AI agents with interactive and autonomous behavior patterns, naming starts to drift. Policy intent gets fuzzy. People read "criticality" or "environment" and assume shared meaning where meaning has already diverged. Then policy scopes become misleading even when the syntax is valid.&lt;/p&gt;

&lt;p&gt;That is the failure mode I care about most. Not policy syntax errors. Policy &lt;em&gt;intent&lt;/em&gt; errors.&lt;/p&gt;

&lt;p&gt;For regulated enterprises, or any organization expecting meaningful agent scale, my default recommendation is to establish a dedicated agent CSA schema and keep crosswalk mappings to legacy workload attributes where needed. You can still align governance. You just stop pretending the populations are identical.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architect's mistake: tactical granularity too early
&lt;/h2&gt;

&lt;p&gt;Most teams that finally commit to an agent schema make the same second mistake: they overengineer it.&lt;/p&gt;

&lt;p&gt;They try to encode every nuanced runtime trait into attributes on day one. They turn schema design into a cataloging exercise. They create dozens of values nobody will govern consistently.&lt;/p&gt;

&lt;p&gt;Do not do that.&lt;/p&gt;

&lt;p&gt;Strategic schema design means defining &lt;em&gt;long-lived control boundaries&lt;/em&gt;, not short-lived implementation detail. Microsoft documents clear limits and lifecycle constraints on custom security attributes, including tenant-level definition caps and immutable naming characteristics, which is exactly why restraint is a design virtue (&lt;a href="https://learn.microsoft.com/entra/fundamentals/custom-security-attributes-overview#limits-and-constraints" rel="noopener noreferrer"&gt;limits and constraints&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/graph/api/resources/custom-security-attributes-overview?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Graph overview&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Start with coarse boundaries that support high-impact policy outcomes you know you will still care about two years from now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two coarse boundaries worth defining first
&lt;/h2&gt;

&lt;p&gt;First boundary: approved workload state.&lt;/p&gt;

&lt;p&gt;If your operating model says "no AI agent should sign in until explicitly approved," then encode exactly that as a first-class classification and enforce from there. This is the kind of architectural control objective that survives platform changes.&lt;/p&gt;

&lt;p&gt;Second boundary: department trust segmentation.&lt;/p&gt;

&lt;p&gt;If your operating model says "financial department agents should only authenticate within finance-defined trust boundaries," then encode that boundary at classification level before you layer finer controls. Entra policy and filtering surfaces are strongest when your classes reflect organizational trust zones, not implementation trivia (&lt;a href="https://learn.microsoft.com/en-us/entra/identity/conditional-access/agent-id#attribute-driven-conditional-access" rel="noopener noreferrer"&gt;attribute-driven Conditional Access for agents&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/entra/identity/conditional-access/agent-id/policy-autonomous-agents#allow-only-specific-agents-to-access-resources" rel="noopener noreferrer"&gt;autonomous agent policy walkthrough&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;These are strategic guardrails. The fine-grained boundaries should come from additional controls and deeper policy patterns, which we can cover in follow-up pieces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Governance is part of schema, not a separate phase
&lt;/h2&gt;

&lt;p&gt;Custom security attributes are security-sensitive by design, and Entra uses dedicated attribute roles for definition and assignment. Even Global Administrator is not automatically enough for these operations by default (&lt;a href="https://learn.microsoft.com/entra/fundamentals/custom-security-attributes-overview#custom-security-attribute-roles" rel="noopener noreferrer"&gt;custom security attribute roles&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/entra/identity/role-based-access-control/permissions-reference#attribute-assignment-administrator" rel="noopener noreferrer"&gt;permissions reference&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Treat that as a feature, not friction.&lt;/p&gt;

&lt;p&gt;Your schema decision should include explicit ownership for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;who defines agent attribute sets and values,&lt;/li&gt;
&lt;li&gt;who is allowed to assign and update values on agent identities,&lt;/li&gt;
&lt;li&gt;how schema changes are reviewed when agent programs evolve.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If those answers are not defined with the schema, your taxonomy will drift faster than your policies can keep up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The practical position
&lt;/h2&gt;

&lt;p&gt;Could you reuse your current workload identity schema for AI agents? Yes.&lt;/p&gt;

&lt;p&gt;Should you, by default, in a large regulated enterprise? Usually no.&lt;/p&gt;

&lt;p&gt;The better default is a dedicated agent schema with a small number of coarse, policy-driving attributes. Make the boundaries obvious. Keep the vocabulary stable. Optimize for long-term policy clarity, not short-term convenience.&lt;/p&gt;

&lt;p&gt;This is architecture work in the most literal sense: defining the shape of control before control logic gets complicated.&lt;/p&gt;

&lt;p&gt;We already did this in this series when discussing dynamic consent accumulation and agent governance pressure in &lt;a href="https://dev.to/astaykov/the-overlooked-gem-in-microsoft-entra-that-gives-your-ai-agents-super-powers-3mde"&gt;The Overlooked Gem in Microsoft Entra&lt;/a&gt; and &lt;a href="https://dev.to/astaykov/your-agent-is-becoming-the-crown-jewel-soc-reviews-and-governance-for-the-dynamic-consent-era-23l3"&gt;Your Agent Is Becoming the Crown Jewel&lt;/a&gt;. This article just names the next prerequisite: the classification layer that keeps your controls honest.&lt;/p&gt;

&lt;p&gt;If you delay this decision, every downstream guardrail becomes harder to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/fundamentals/custom-security-attributes-overview" rel="noopener noreferrer"&gt;What are custom security attributes in Microsoft Entra ID?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/resources/custom-security-attributes-overview?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Overview of custom security attributes using Microsoft Graph API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/identity/enterprise-apps/custom-security-attributes-apps" rel="noopener noreferrer"&gt;Manage custom security attributes for an application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/conditional-access/agent-id#attribute-driven-conditional-access" rel="noopener noreferrer"&gt;Conditional Access for agents (attribute-driven Conditional Access)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/conditional-access/agent-id/policy-autonomous-agents#allow-only-specific-agents-to-access-resources" rel="noopener noreferrer"&gt;Conditional Access for autonomous agents (allow only specific agents to access resources)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID key concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/agent-service-principals" rel="noopener noreferrer"&gt;Agent identities, service principals, and applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/identity/role-based-access-control/permissions-reference#attribute-assignment-administrator" rel="noopener noreferrer"&gt;Role permissions reference: Attribute Assignment Administrator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>entraagentid</category>
      <category>customsecurityattributes</category>
      <category>aiagents</category>
      <category>zerotrust</category>
    </item>
    <item>
      <title>How enterprise architects should decide Entra Agent ID blueprint boundaries for non-Microsoft platforms</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Tue, 21 Jul 2026 10:47:00 +0000</pubDate>
      <link>https://dev.to/astaykov/how-enterprise-architects-should-decide-entra-agent-id-blueprint-boundaries-for-non-microsoft-oaa</link>
      <guid>https://dev.to/astaykov/how-enterprise-architects-should-decide-entra-agent-id-blueprint-boundaries-for-non-microsoft-oaa</guid>
      <description>&lt;p&gt;Enterprise architects keep asking me the same question: &lt;em&gt;how many agent identity blueprints should we create&lt;/em&gt; for third-party or custom agent platforms connected to Microsoft Entra Agent ID?&lt;/p&gt;

&lt;p&gt;That question sounds operational, but it is architectural. You are deciding failure containment, ownership boundaries, and governance behavior, all at once.&lt;/p&gt;

&lt;p&gt;Before we go deeper, one important acknowledgement. If your agents are built in Microsoft-managed builder paths such as Copilot Studio and Agent 365 integration flows, identity provisioning is largely handled for you, including automatic Agent ID creation and shared blueprint behavior in that platform path (&lt;a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/admin-use-entra-agent-identities" rel="noopener noreferrer"&gt;Copilot Studio automatic Agent IDs&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/microsoft-agent-365/builder/identity" rel="noopener noreferrer"&gt;Agent 365 identity integration&lt;/a&gt;). If you choose that platform, you also accept its blueprint identity model by design.&lt;/p&gt;

&lt;p&gt;This article is for the other world: non-Microsoft-built agent platforms, where your enterprise architecture team owns the blueprint boundary decisions.&lt;/p&gt;

&lt;p&gt;I am also not going to summarize the canonical guidance. You should read both &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/how-to-plan-agent-identity-architecture" rel="noopener noreferrer"&gt;Plan your agent identity architecture&lt;/a&gt; and &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/concept-agent-id-design-patterns" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID design patterns&lt;/a&gt; directly, then come back. This piece is about decision framing, trade-offs, and policy posture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop asking for a count, start defining trust boundaries
&lt;/h2&gt;

&lt;p&gt;When architects ask "how many blueprints," they usually mean one of three fears:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"I do not want one compromised component to become tenant-wide damage."&lt;/li&gt;
&lt;li&gt;"I do not want central identity teams to become a ticket bottleneck."&lt;/li&gt;
&lt;li&gt;"I do not want unrecoverable sprawl six months from now."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is a trust-boundary problem, not an object-count problem.&lt;/p&gt;

&lt;p&gt;Microsoft's own architecture guidance is explicit that blueprint count should follow trust boundaries, while many common concerns (replicas, memory partitioning, session context) are not valid reasons to split identities (&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/how-to-plan-agent-identity-architecture" rel="noopener noreferrer"&gt;planning guidance&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/concept-agent-id-design-patterns" rel="noopener noreferrer"&gt;design patterns&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If your team still starts with org chart lines like "one blueprint per project by default," you are optimizing for slide readability, not for incident containment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The blueprint power model, and the part teams keep confusing
&lt;/h2&gt;

&lt;p&gt;You need one clear mental model.&lt;/p&gt;

&lt;p&gt;The blueprint is your identity factory and authentication anchor. It is what enables creation of child agent identities at scale, including runtime or ephemeral patterns when your architecture needs on-demand identities (&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-id-creation-channels" rel="noopener noreferrer"&gt;creation channels&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That is good news for delivery teams. Developers do not need to raise a central ticket for every single new identity if the right blueprint channel and controls are already in place.&lt;/p&gt;

&lt;p&gt;But do not confuse that with automatic governance.&lt;/p&gt;

&lt;p&gt;Blueprints are not where your organization magically enforces business access policy. Consent boundaries, entitlement policy, Conditional Access, and app-governance controls are separate control planes that still require explicit enterprise policy definition and rollout (&lt;a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/user-admin-consent-overview" rel="noopener noreferrer"&gt;user/admin consent model&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/identity-governance-applications-define" rel="noopener noreferrer"&gt;define governance policy&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Treat the blueprint as a creation authority, not as the permission-grant layer and not as your per-agent lifecycle governance switch.&lt;/p&gt;

&lt;p&gt;In plain terms, Entra Agent ID and Agent 365 capabilities do not enforce your internal architecture doctrine by themselves. Without internal policies, teams will improvise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blast radius reality: one compromised agent can become many identities
&lt;/h2&gt;

&lt;p&gt;Here is the uncomfortable part.&lt;/p&gt;

&lt;p&gt;Within a shared blueprint trust boundary, if one agent runtime is compromised and the attacker can use the same blueprint credential path, that attacker can request tokens that act as sibling identities under that blueprint boundary. This is exactly why Microsoft frames blueprint compromise as potentially affecting all child identities in that blueprint scope (&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/how-to-plan-agent-identity-architecture" rel="noopener noreferrer"&gt;planning guidance&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That is the architectural reason you model by trust boundary first.&lt;/p&gt;

&lt;p&gt;It also explains a frequent false comfort pattern: "we will just split certificates or managed identity details but keep one shared blueprint boundary." If the effective authentication authority is still the same blueprint trust surface, your containment gain is smaller than people assume.&lt;/p&gt;

&lt;h2&gt;
  
  
  A risk-first decision framework for blueprint boundaries
&lt;/h2&gt;

&lt;p&gt;Use this sequence. Do not skip steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Define hard trust boundaries
&lt;/h3&gt;

&lt;p&gt;Map runtime, secret stores, network segmentation, and operational ownership. If compromise should not cross between two zones, they should not share a blueprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Define failure containment targets
&lt;/h3&gt;

&lt;p&gt;State explicitly what should be kill-switch scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one identity,&lt;/li&gt;
&lt;li&gt;one blueprint,&lt;/li&gt;
&lt;li&gt;one environment,&lt;/li&gt;
&lt;li&gt;or tenant-wide.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this is undefined, your incident response design is fiction.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Define permission topology
&lt;/h3&gt;

&lt;p&gt;Decide what is inheritable baseline and what is per-agent specialization. Keep inherited baseline tight and role-specific differentiation local to agent identities.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Define lifecycle behavior
&lt;/h3&gt;

&lt;p&gt;Will identities be long-lived, or created dynamically for specific task windows? If dynamic creation is a first-class requirement, blueprint channel design and guardrails become even more critical.&lt;/p&gt;

&lt;h3&gt;
  
  
  5) Define governance ownership
&lt;/h3&gt;

&lt;p&gt;Who approves what, who can create via which channel, who can override in emergencies, who attests quarterly. If there is no owner matrix, there is no governance.&lt;/p&gt;

&lt;h2&gt;
  
  
  When one blueprint is right, and when it is reckless
&lt;/h2&gt;

&lt;p&gt;One blueprint with multiple agent identities is often correct when teams share the same trust boundary, runtime envelope, and operational ownership, while still needing per-agent attribution and differentiated downstream access (&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/concept-agent-id-design-patterns" rel="noopener noreferrer"&gt;design patterns&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Concrete example: if your agents run in the same container orchestration boundary (for example, a shared Kubernetes namespace on AKS, EKS, or GKE), that is usually a strong indicator for one shared blueprint in that boundary. In practice, namespace-level controls define who can deploy, who can mutate workloads, what network policies apply, and what mounted/shared resources are reachable.&lt;/p&gt;

&lt;p&gt;That matters because your real security perimeter is often the namespace and its attached runtime controls, not an individual pod. Most engineering organizations can consistently enforce controls at namespace scope for developers and CI/CD pipelines, while per-pod isolation is harder to guarantee as a durable operating model.&lt;/p&gt;

&lt;p&gt;It becomes reckless when you cross security domains and still keep one blueprint for convenience. Separate teams, separate secret domains, separate runtime isolation, or separate regulatory boundaries should usually trigger separate blueprints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Policy starter kit for enterprise architects
&lt;/h2&gt;

&lt;p&gt;If you want consistency across teams, publish a short internal policy before the next project starts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blueprint policy baseline
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One blueprint per trust boundary unless exception approved.&lt;/li&gt;
&lt;li&gt;Mandatory sponsor and owner assignment, with periodic attestation.&lt;/li&gt;
&lt;li&gt;Naming convention that encodes environment, domain, and business owner.&lt;/li&gt;
&lt;li&gt;Conditional Access baseline and monitoring baseline applied at blueprint and identity levels where applicable (&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/best-practices-agent-id" rel="noopener noreferrer"&gt;best practices&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/manage-agent-identities-admin" rel="noopener noreferrer"&gt;manage and govern agent identities&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creation channel policy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Define which channels are allowed in your org: admin center, Graph, IaC/CLI, product-integrated channels.&lt;/li&gt;
&lt;li&gt;Bind each channel to approved roles and permission grants.&lt;/li&gt;
&lt;li&gt;Prohibit ad-hoc consent paths for production-grade identity creation unless explicitly reviewed (&lt;a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-user-consent" rel="noopener noreferrer"&gt;configure user consent&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Split and merge rubric
&lt;/h3&gt;

&lt;p&gt;Require architecture review on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;trust-boundary changes,&lt;/li&gt;
&lt;li&gt;new regulated data exposure,&lt;/li&gt;
&lt;li&gt;new external execution platform,&lt;/li&gt;
&lt;li&gt;incident lessons that show containment gaps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If teams cannot explain why two workloads can safely share compromise blast radius, they should not share a blueprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architect checklist to force before production
&lt;/h2&gt;

&lt;p&gt;Before approving blueprint design, require crisp answers to these questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If one agent runtime is compromised, what exact identity scope can the attacker influence?&lt;/li&gt;
&lt;li&gt;Which trust boundaries are represented, and why are they safe to share?&lt;/li&gt;
&lt;li&gt;Which channels can create identities, and who controls them?&lt;/li&gt;
&lt;li&gt;Which policies prevent consent and permission sprawl?&lt;/li&gt;
&lt;li&gt;What is the fastest kill-switch path during incident response?&lt;/li&gt;
&lt;li&gt;What quarterly evidence proves this model is still valid?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your team cannot answer those six questions in one review, your blueprint model is not ready for production.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/concept-agent-id-design-patterns" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID design patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/how-to-plan-agent-identity-architecture" rel="noopener noreferrer"&gt;Plan your agent identity architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/admin-use-entra-agent-identities" rel="noopener noreferrer"&gt;Automatically create Microsoft Entra Agent IDs for Copilot Studio agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/microsoft-agent-365/builder/identity" rel="noopener noreferrer"&gt;Agent identity integration for Copilot Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-id-creation-channels" rel="noopener noreferrer"&gt;How are agent identities created?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/best-practices-agent-id" rel="noopener noreferrer"&gt;Best practices for Microsoft Entra Agent ID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/user-admin-consent-overview" rel="noopener noreferrer"&gt;Overview of user and admin consent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-user-consent" rel="noopener noreferrer"&gt;Configure how users consent to applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/identity-governance-applications-define" rel="noopener noreferrer"&gt;Define organizational policies for governing access to applications in your environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/identity-governance-applications-deploy" rel="noopener noreferrer"&gt;Deploying organizational policies for governing access to applications integrated with Microsoft Entra ID&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>entraagentid</category>
      <category>identitygovernance</category>
      <category>aiagents</category>
      <category>zerotrust</category>
    </item>
    <item>
      <title>The industry does not have an agent identity propagation standard yet</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Tue, 14 Jul 2026 11:07:00 +0000</pubDate>
      <link>https://dev.to/astaykov/the-industry-does-not-have-an-agent-identity-propagation-standard-yet-3fmf</link>
      <guid>https://dev.to/astaykov/the-industry-does-not-have-an-agent-identity-propagation-standard-yet-3fmf</guid>
      <description>&lt;p&gt;Most architecture conversations about AI agents still get stuck on the wrong boundary.&lt;/p&gt;

&lt;p&gt;Someone draws an agent in Azure, another agent in AWS, a resource behind Ping Identity or Auth0, a Microsoft Entra-protected API, an MCP server in the middle, and a user somewhere at the beginning of the chain. Then the room asks: can Microsoft Entra Agent ID work if the agent is not hosted on Microsoft infrastructure?&lt;/p&gt;

&lt;p&gt;That is the easy question. Hosting is not the boundary.&lt;/p&gt;

&lt;p&gt;Identity provider domain is the boundary.&lt;/p&gt;

&lt;p&gt;An application can live in AWS, Google Cloud, a co-location rack, or a basement server room and still use Microsoft Entra ID for sign-in. The same principle applies to agents. Microsoft explicitly positions Entra Agent ID as working with Microsoft and non-Microsoft platforms, including integrations through the Microsoft Entra Auth SDK sidecar and workload identity federation (&lt;a href="https://learn.microsoft.com/entra/agent-id/what-is-microsoft-entra-agent-id" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/entra/agent-id/configure-third-party-agents" rel="noopener noreferrer"&gt;third-party agent integration patterns&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The hard part starts when the flow leaves one identity provider and must preserve the original user context in another identity provider's world.&lt;/p&gt;

&lt;p&gt;That is where the industry is still awkward. Not because there are no standards. There are standards. The problem is that the standards describe token exchange mechanics better than they describe enterprise trust governance for long, agentic, multi-hop chains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa8lh33gibedd8dmb6uou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa8lh33gibedd8dmb6uou.png" alt="A user starts in one identity provider domain, passes through agents, MCP servers, and resources, then crosses into another identity provider domain before returning to downstream APIs. The hard part is not hosting. The hard part is preserving trustworthy user context across identity provider boundaries." width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram above is the mental model. A user signs in, an application invokes an agent, the agent calls a tool or MCP server, another agent appears, and eventually a REST API or database needs to decide whether to trust the original user's context. Some arrows stay inside Microsoft Entra. Some arrows cross into Ping Identity or another provider. Some resources are custom APIs. Some are Microsoft resources. Some are agentic systems calling other agentic systems.&lt;/p&gt;

&lt;p&gt;The diagram looks like a flow. In practice, it is a chain of trust decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Federation is not token exchange
&lt;/h2&gt;

&lt;p&gt;One of the most useful audience questions in the discussion was simple: "We already solve multiple identity providers with federation. Why is this different for agents?"&lt;/p&gt;

&lt;p&gt;That question matters because it separates two things teams often blend together.&lt;/p&gt;

&lt;p&gt;Federation solves an interactive authentication problem. A user starts at one identity provider, is redirected to another identity provider, proves who they are, and returns with a token or assertion the application can use. That pattern is well understood in SAML, OpenID Connect, and enterprise SSO designs (&lt;a href="https://openid.net/specs/openid-connect-core-1_0.html" rel="noopener noreferrer"&gt;OpenID Connect Core&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/entra/identity-platform/v2-protocols-oidc" rel="noopener noreferrer"&gt;Microsoft identity platform and OpenID Connect&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Token exchange solves a different problem. A component that already received one token asks an authorization server for another token intended for a different resource or context. The standard that most directly describes this is &lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html" rel="noopener noreferrer"&gt;OAuth 2.0 Token Exchange, RFC 8693&lt;/a&gt;. RFC 8693 defines a Security Token Service style protocol for requesting and obtaining tokens from OAuth authorization servers, including delegation and impersonation semantics.&lt;/p&gt;

&lt;p&gt;Those are not the same motion.&lt;/p&gt;

&lt;p&gt;Federation is the front door. Token exchange is what happens in the hallway after the front door has already closed.&lt;/p&gt;

&lt;p&gt;That distinction becomes brutally important for agents because agents create more hallways. A user does not simply sign in and call one API. The user asks an agent, the agent calls a tool, the tool calls an MCP server, the MCP server calls another agent, and that agent calls a REST API. Each hop may need a different token audience, a different scope, a different policy evaluation, and a different interpretation of who is acting.&lt;/p&gt;

&lt;h2&gt;
  
  
  RFC 8693 gives us language, not the whole operating model
&lt;/h2&gt;

&lt;p&gt;RFC 8693 is important because it gives the industry precise words for what keeps showing up in agent conversations: &lt;code&gt;subject_token&lt;/code&gt;, &lt;code&gt;actor_token&lt;/code&gt;, &lt;code&gt;audience&lt;/code&gt;, &lt;code&gt;resource&lt;/code&gt;, &lt;code&gt;scope&lt;/code&gt;, &lt;code&gt;act&lt;/code&gt;, and &lt;code&gt;may_act&lt;/code&gt; (&lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html" rel="noopener noreferrer"&gt;RFC 8693&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;It also draws a clean line between impersonation and delegation. In impersonation, principal A becomes indistinguishable from principal B within the token's rights context. In delegation, principal A remains visible as the actor representing principal B (&lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html#section-1.1" rel="noopener noreferrer"&gt;RFC 8693, delegation vs. impersonation&lt;/a&gt;). For agents, that distinction is not academic. An enterprise should almost never want an agent to become invisible as the human. It wants the user, the agent, and the delegation relationship to remain visible.&lt;/p&gt;

&lt;p&gt;RFC 8693 also defines the &lt;code&gt;act&lt;/code&gt; claim as a way to represent the current actor and even nested actor chains in a JWT (&lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html#section-4.1" rel="noopener noreferrer"&gt;RFC 8693, actor claim&lt;/a&gt;). That sounds like exactly what we need.&lt;/p&gt;

&lt;p&gt;But the standard is careful about its own boundary. It defines a protocol. It does not solve every deployment trust model. It explicitly leaves token semantics, policy decisions, and many security characteristics to implementations and deployment configuration (&lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html#section-1" rel="noopener noreferrer"&gt;RFC 8693 introduction&lt;/a&gt;, &lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html#section-5" rel="noopener noreferrer"&gt;RFC 8693 security considerations&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That is the gap.&lt;/p&gt;

&lt;p&gt;The standard can describe a token exchange. It cannot, by itself, answer the enterprise question: who configured the mapping that allows an actor from identity provider A to arrive at identity provider B and claim a privileged user context?&lt;/p&gt;

&lt;p&gt;That question is not protocol syntax. That question is governance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autonomous agents are the solved part
&lt;/h2&gt;

&lt;p&gt;If there is no user context to preserve, the picture is much cleaner.&lt;/p&gt;

&lt;p&gt;An autonomous agent can authenticate as itself using client credentials, a certificate, a federated identity credential, or a managed identity, depending on the platform and operating model. Microsoft Entra Agent ID supports autonomous access and delegated access as different modes for agent identities (&lt;a href="https://learn.microsoft.com/entra/agent-id/what-are-agent-identities#what-agent-identities-enable" rel="noopener noreferrer"&gt;what agent identities enable&lt;/a&gt;). The Microsoft Entra Auth SDK sidecar is not the authentication method for the agent itself. It is a token-handling pattern that keeps credential exchange, OBO flows, token caching, and credential-source abstraction outside the agent code (&lt;a href="https://learn.microsoft.com/entra/agent-id/authentication-with-auth-sdk-sidecar" rel="noopener noreferrer"&gt;Microsoft Entra Auth SDK sidecar&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This is also where workload identity federation fits well. Microsoft documents workload identity federation as a way for applications to access Microsoft Entra-protected resources without managing secrets, by trusting tokens from external identity providers (&lt;a href="https://learn.microsoft.com/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;workload identity federation&lt;/a&gt;). Entra Agent ID's third-party integration guidance describes agents on external platforms exchanging native workload identity tokens for Microsoft Entra tokens before calling APIs (&lt;a href="https://learn.microsoft.com/entra/agent-id/configure-third-party-agents" rel="noopener noreferrer"&gt;integrate third-party agents&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This pattern is not limited to Microsoft. AWS, Google Cloud, Kubernetes ecosystems, and SPIFFE-based systems all lean into the same broad direction: give workloads short-lived, attestable identities instead of static secrets. SPIFFE describes itself as a set of open-source standards for identifying software systems in dynamic and heterogeneous environments, with short-lived identity documents called SVIDs delivered through a workload API (&lt;a href="https://spiffe.io/docs/latest/spiffe-about/overview/" rel="noopener noreferrer"&gt;SPIFFE overview&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;For fully autonomous agents, the industry has enough pieces to build sane systems today.&lt;/p&gt;

&lt;p&gt;The agent proves what workload it is. The target resource validates the token. The authorization system checks the agent's assigned rights. No human context needs to survive the journey.&lt;/p&gt;

&lt;p&gt;That is not trivial, but it is tractable.&lt;/p&gt;

&lt;h2&gt;
  
  
  User context is where the floor drops
&lt;/h2&gt;

&lt;p&gt;The difficult case is the one the audience kept circling back to: an employee signs in, an agent acts on behalf of that employee, the flow crosses identity providers, and a downstream resource must still know which human user started the journey.&lt;/p&gt;

&lt;p&gt;Microsoft Entra Agent ID supports on-behalf-of flows for agents. The documented OBO pattern uses a user token sent to the agent identity blueprint, then performs token exchanges so the resulting resource token carries the signed-in user's delegated context together with the agent identity (&lt;a href="https://learn.microsoft.com/entra/agent-id/agent-on-behalf-of-oauth-flow" rel="noopener noreferrer"&gt;Agent OAuth flows: on behalf of flow&lt;/a&gt;). Microsoft recommends using approved SDKs such as Microsoft.Identity.Web or the Microsoft Entra Auth SDK sidecar because manual implementation is complex and error-prone (&lt;a href="https://learn.microsoft.com/entra/agent-id/agent-on-behalf-of-oauth-flow" rel="noopener noreferrer"&gt;Agent OAuth flows: on behalf of flow&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/entra/agent-id/authentication-with-auth-sdk-sidecar#sidecar-sample-scenarios" rel="noopener noreferrer"&gt;sidecar sample scenarios&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Inside one coherent identity domain, that is already a serious amount of machinery. Across identity providers, it becomes a trust governance problem.&lt;/p&gt;

&lt;p&gt;The downstream system is no longer asking only, "Is this token valid?" It is asking a longer set of questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who was the original user?&lt;/li&gt;
&lt;li&gt;Which agent is acting now?&lt;/li&gt;
&lt;li&gt;Which prior agents or services participated in the chain?&lt;/li&gt;
&lt;li&gt;Which identity provider translated the context?&lt;/li&gt;
&lt;li&gt;Who configured that translation?&lt;/li&gt;
&lt;li&gt;Are we allowed to trust that mapping?&lt;/li&gt;
&lt;li&gt;How do we monitor and revoke that trust when risk changes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where the diagram matters. Six hops are not theoretical in an agentic architecture. They are what happens when a human asks one assistant to do work that uses an MCP server, which delegates to another specialized agent, which calls a vendor API, which then calls an internal API.&lt;/p&gt;

&lt;p&gt;The standards do not stop you from creating such a chain. OAuth OBO style flows do not impose a natural business limit on how many middle tiers can appear. RFC 8693 can represent actor chains through nested &lt;code&gt;act&lt;/code&gt; claims. In theory, the chain can keep growing (&lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html#section-4.1" rel="noopener noreferrer"&gt;RFC 8693 actor claim&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Then the old boring transport layer walks into the room.&lt;/p&gt;

&lt;p&gt;Bearer tokens are commonly presented to resource servers in the HTTP &lt;code&gt;Authorization&lt;/code&gt; header field using &lt;code&gt;Authorization: Bearer ...&lt;/code&gt; (&lt;a href="https://www.rfc-editor.org/rfc/rfc6750.html#section-2.1" rel="noopener noreferrer"&gt;RFC 6750, authorization request header field&lt;/a&gt;). HTTP deliberately does not define one universal maximum length for a field line, field value, or header section. Implementations set their own limits, and a server that receives request fields larger than it is willing to process is supposed to reject the request with an appropriate 4xx response, not ignore the fields (&lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-field-limits" rel="noopener noreferrer"&gt;RFC 9110, field limits&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That means a perfectly valid access token can still be operationally too large for one proxy, gateway, service mesh sidecar, WAF, CDN edge, or application server in the path.&lt;/p&gt;

&lt;p&gt;This is not only an availability problem. It is a security design smell. If every delegated hop adds nested actors, subjects, issuers, audiences, or other chain evidence, the token can grow until one component in the HTTP path handles it differently than the component that issued it or the API that validates it. Best case, the call fails cleanly. Worse case, a proxy truncates, drops, rewrites, retries, normalizes, caches, or falls back in a way the authorization model never expected. HTTP itself warns that ignoring oversized header fields increases exposure to request smuggling, and its security considerations explicitly call out attacks via protocol element length (&lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-field-limits" rel="noopener noreferrer"&gt;RFC 9110, field limits&lt;/a&gt;, &lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-attacks-via-protocol-elemen" rel="noopener noreferrer"&gt;RFC 9110, attacks via protocol element length&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This is how a governance problem becomes an incident report. The identity system issued a token that was cryptographically valid. The architecture allowed a chain long enough to make that token huge. The application team assumed middleware would fail closed. The proxy team assumed the upstream API owned authorization. Then an agent reaches data it should not see because one hop in the path handled an oversized credential differently than another.&lt;/p&gt;

&lt;p&gt;Who owns that failure?&lt;/p&gt;

&lt;p&gt;The vendor that supported unbounded chaining? The architect who allowed policies with no practical chain-depth ceiling? The developer who never measured token size or actor-chain depth? The HTTP proxy that mishandled an oversized &lt;code&gt;Authorization&lt;/code&gt; header? The operations team that changed a WAF limit two months ago and did not know it was now part of the identity control plane?&lt;/p&gt;

&lt;p&gt;This is why "it worked two months ago" is such a dangerous sentence in agent identity. Nothing in the agent code needs to change for the chain to become too long. More tools get added. More agents call each other. More claims get preserved for audit. More tenants and issuers appear. Suddenly the same logical flow produces a larger token, crosses a different intermediary, and starts failing. Or worse, failing open.&lt;/p&gt;

&lt;p&gt;But a representable chain is not automatically a governable chain.&lt;/p&gt;

&lt;p&gt;That is the industry's current problem in one sentence: we can describe the chain better than we can govern the chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evidence helps, but it does not create trust
&lt;/h2&gt;

&lt;p&gt;Once the conversation moves from "can I get a token?" to "can the downstream system understand the context?" teams naturally reach for more data in the token.&lt;/p&gt;

&lt;p&gt;That instinct is reasonable, but it is also incomplete. A downstream resource may need to know whether the caller is an agent, which agent is acting, which human user is present, which tenant owns the agent, whether the human is external to the resource tenant, or whether the agent is multi-tenant. That context can make downstream decisions smarter.&lt;/p&gt;

&lt;p&gt;But more evidence in a token is not the same as trust.&lt;/p&gt;

&lt;p&gt;Adding agent context, actor context, tenant context, or multi-tenant application context can make a downstream authorization decision more informed. It does not answer who approved the mapping, whether the source domain is trusted, whether the chain is still valid, or how the receiving domain should react when a risk signal changes.&lt;/p&gt;

&lt;p&gt;That is the mistake to avoid. Token evidence can describe what arrived. Governance decides whether what arrived should be trusted.&lt;/p&gt;

&lt;p&gt;The difference matters. Carrying context is easier than proving that the context should be trusted across organizational, identity provider, and agent boundaries.&lt;/p&gt;

&lt;h2&gt;
  
  
  The emerging standards conversation is really about trust evidence
&lt;/h2&gt;

&lt;p&gt;When people ask for "the standard," they often mean one protocol that makes the whole diagram safe. That is not how this will land.&lt;/p&gt;

&lt;p&gt;The industry is moving along several tracks at once.&lt;/p&gt;

&lt;p&gt;OAuth token exchange gives us the exchange grammar (&lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html" rel="noopener noreferrer"&gt;RFC 8693&lt;/a&gt;). Workload identity federation gives us a workable model for autonomous workload trust without secrets (&lt;a href="https://learn.microsoft.com/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;workload identity federation&lt;/a&gt;). SPIFFE gives us an identity framework for workloads in heterogeneous environments, including JWT and X.509 identity documents (&lt;a href="https://spiffe.io/docs/latest/spiffe-about/overview/" rel="noopener noreferrer"&gt;SPIFFE overview&lt;/a&gt;). Shared Signals and CAEP give the ecosystem a way to communicate security events and state changes continuously, rather than treating access decisions as one-time snapshots (&lt;a href="https://openid.net/wg/sharedsignals/" rel="noopener noreferrer"&gt;OpenID Shared Signals Working Group&lt;/a&gt;). Agent protocols such as MCP and A2A are pushing tool and agent communication into more formal shapes, and Microsoft explicitly lists OAuth 2.0, MCP, and A2A among the protocols supported by the Entra Agent identity platform (&lt;a href="https://learn.microsoft.com/entra/agent-id/what-is-microsoft-entra-agent-id" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The center of gravity is shifting from "can I exchange a token?" to "what evidence travels with the token, and who is accountable for trusting it?"&lt;/p&gt;

&lt;p&gt;That is the right shift.&lt;/p&gt;

&lt;p&gt;The next generation of standards work has to answer questions the current protocol layer only exposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How does a receiving domain know the original user is still the same user after multiple agent and tool hops?&lt;/li&gt;
&lt;li&gt;How does the chain preserve both the human subject and the current agent actor without collapsing into impersonation?&lt;/li&gt;
&lt;li&gt;How are identity provider mappings approved, reviewed, expired, and revoked?&lt;/li&gt;
&lt;li&gt;How does a downstream resource distinguish a first-party enterprise agent from a multi-tenant external agent acting for an enterprise user?&lt;/li&gt;
&lt;li&gt;How do risk signals travel fast enough that a compromised account or agent does not keep operating on stale trust?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of those questions are solved by adding one more token parameter.&lt;/p&gt;

&lt;p&gt;They require standards that combine identity evidence, delegation semantics, risk signaling, authorization policy, and observability.&lt;/p&gt;

&lt;h2&gt;
  
  
  What architects should do now
&lt;/h2&gt;

&lt;p&gt;The correct response is not to wait for the perfect standard. It is to design with the current product and trust boundary in mind.&lt;/p&gt;

&lt;p&gt;First, separate platform location from identity provider domain. An agent running in AWS can still use Microsoft Entra Agent ID. An agent running in Azure can still call a Ping-protected resource. The host is an implementation detail. The issuer, audience, subject, actor, and trust mapping are the security model (&lt;a href="https://learn.microsoft.com/entra/agent-id/configure-third-party-agents" rel="noopener noreferrer"&gt;third-party agent integration patterns&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Second, split autonomous agent flows from user-delegated flows before you draw the final architecture. Autonomous flows can be built today with client credentials, certificates, federated identity credentials, managed identities, workload identity federation, and standard token validation. A sidecar can help keep token acquisition and credential handling out of the agent code, but it is not itself the agent authentication method.&lt;/p&gt;

&lt;p&gt;The delegated case is different. With Entra Agent ID today, do not design for an OBO flow that carries Microsoft Entra user context across an identity provider boundary and expects the other domain to preserve that context as part of the same delegation chain. Entra Agent ID supports OBO patterns for agents, but cross-IDP user-context propagation is not the supported operating model (&lt;a href="https://learn.microsoft.com/entra/agent-id/agent-on-behalf-of-oauth-flow" rel="noopener noreferrer"&gt;Agent OAuth OBO flow&lt;/a&gt;). If the downstream system is governed by another identity provider, treat that as a separate trust domain. Either keep the delegated path inside one identity provider boundary, use autonomous workload-to-workload trust where user context is not required, or design an explicit application-level handoff with its own audit and policy model.&lt;/p&gt;

&lt;p&gt;Third, avoid cross-domain impersonation unless the business process genuinely requires it and the audit model can survive scrutiny. Delegation should preserve the actor. Impersonation hides the actor from the resource's practical decision point. For agents, hiding the actor is usually the wrong instinct (&lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html#section-1.1" rel="noopener noreferrer"&gt;RFC 8693 delegation vs. impersonation&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The real standard we are missing
&lt;/h2&gt;

&lt;p&gt;The industry does not lack token standards. It lacks a complete, interoperable &lt;em&gt;agent identity propagation governance model&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That model must preserve the original user where appropriate, preserve the current agent actor always, make cross-IDP mappings explicit, carry enough evidence for downstream decisions, propagate risk and revocation signals, and give enterprises a way to audit who allowed which transition.&lt;/p&gt;

&lt;p&gt;OAuth token exchange is part of that answer. Workload identity federation is part of that answer. SPIFFE is part of that answer. Shared Signals and CAEP are part of that answer. Agent-specific identity platforms such as Microsoft Entra Agent ID are part of that answer.&lt;/p&gt;

&lt;p&gt;But no single one of them is the whole answer yet.&lt;/p&gt;

&lt;p&gt;That is the uncomfortable but useful conclusion from the diagram. We can build useful agent identity systems today. We can secure autonomous agents today. We can do delegated agent flows inside well-understood trust boundaries today. We can even cross platforms without much drama when the flow is autonomous or the trust boundary is explicit.&lt;/p&gt;

&lt;p&gt;The thing we cannot hand-wave is multi-hop, user-bound, cross-IDP identity propagation.&lt;/p&gt;

&lt;p&gt;That is the work ahead. Not just for Microsoft. For the industry.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/what-is-microsoft-entra-agent-id" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/what-are-agent-identities" rel="noopener noreferrer"&gt;What are agent identities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/configure-third-party-agents" rel="noopener noreferrer"&gt;Integrate third-party agents with Microsoft Entra Agent ID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/authentication-with-auth-sdk-sidecar" rel="noopener noreferrer"&gt;Authentication with Microsoft Entra Auth SDK sidecar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/agent-on-behalf-of-oauth-flow" rel="noopener noreferrer"&gt;Agent OAuth flows: on behalf of flow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;Microsoft Entra workload identity federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/identity-platform/v2-protocols-oidc" rel="noopener noreferrer"&gt;Microsoft identity platform and OpenID Connect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html" rel="noopener noreferrer"&gt;OAuth 2.0 Token Exchange, RFC 8693&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc6750.html" rel="noopener noreferrer"&gt;OAuth 2.0 Bearer Token Usage, RFC 6750&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html" rel="noopener noreferrer"&gt;HTTP Semantics, RFC 9110&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openid.net/specs/openid-connect-core-1_0.html" rel="noopener noreferrer"&gt;OpenID Connect Core 1.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spiffe.io/docs/latest/spiffe-about/overview/" rel="noopener noreferrer"&gt;SPIFFE overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openid.net/wg/sharedsignals/" rel="noopener noreferrer"&gt;OpenID Shared Signals Working Group&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>entraagentid</category>
      <category>identitystandards</category>
      <category>oauth</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>Access packages are the control plane for Entra Agent ID permissions</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Thu, 09 Jul 2026 10:43:00 +0000</pubDate>
      <link>https://dev.to/astaykov/access-packages-are-the-control-plane-for-entra-agent-id-permissions-4kph</link>
      <guid>https://dev.to/astaykov/access-packages-are-the-control-plane-for-entra-agent-id-permissions-4kph</guid>
      <description>&lt;p&gt;It has been a couple of months since &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID became generally available&lt;/a&gt;, but the same message keeps landing in my inbox: "How do we grant permissions to an agent identity? There is no API Permissions page in Entra."&lt;/p&gt;

&lt;p&gt;That moment is always interesting. The team thinks they found a product gap. What they actually found is a mental-model gap.&lt;/p&gt;

&lt;p&gt;Most engineering organizations still design identity the old way: define a permission set early, grant it once, and treat that grant as stable infrastructure. That was already brittle for conventional apps. For agents, it is worse. An agent is useful &lt;em&gt;because&lt;/em&gt; it encounters new contexts, new tools, and new data surfaces after go-live.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/astaykov/a-transformational-ai-agent-does-not-start-with-the-permissions-it-needs-4g8l"&gt;A transformational AI agent does not start with the permissions it needs&lt;/a&gt;, I argued that serious agents should start narrow and &lt;em&gt;earn&lt;/em&gt; scope over time. This article is the governance architecture behind that claim.&lt;/p&gt;

&lt;h2&gt;
  
  
  The portal is not missing a button, your architecture is missing a layer
&lt;/h2&gt;

&lt;p&gt;Entra Agent ID does not erase consent. It does not replace consent. It does not invent a magical fourth mode of consent.&lt;/p&gt;

&lt;p&gt;Consent fundamentals remain exactly what Microsoft documents for enterprise applications: &lt;a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/user-admin-consent-overview" rel="noopener noreferrer"&gt;user consent and admin consent are still the core model&lt;/a&gt;. If delegated access is allowed by policy, a user can authorize it. If risk or scope requires stronger control, admin consent is required.&lt;/p&gt;

&lt;p&gt;That is the first important correction: the "no API permissions blade" observation should not lead to panic. It should lead to design. Agent identities are still bound to Entra authorization rules, including the &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/authorization-agent-id" rel="noopener noreferrer"&gt;Agent ID authorization model for delegated and application permissions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The missing thing is not a tab. The missing thing is an &lt;em&gt;operating path&lt;/em&gt; for controlled permission growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consent semantics are unchanged, enterprise consent posture is still strict
&lt;/h2&gt;

&lt;p&gt;Some architects respond with: "Fine, let users consent as the agent discovers new needs."&lt;/p&gt;

&lt;p&gt;Technically, that is an option in specific policy configurations. Operationally, most enterprises do not live there.&lt;/p&gt;

&lt;p&gt;Real-world tenants often clamp user consent tightly with explicit &lt;a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-user-consent?pivots=portal" rel="noopener noreferrer"&gt;tenant-level consent settings&lt;/a&gt;, because delegated access can expose sensitive workloads very quickly when control boundaries are weak. Security teams are not being stubborn here. They are pattern matching from years of experience.&lt;/p&gt;

&lt;p&gt;So we end up with a familiar tension:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI platform teams need agents that adapt at runtime.&lt;/li&gt;
&lt;li&gt;Governance teams need approvals, accountability, and least-standing-privilege.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you force one side to "win," you get predictable failure modes. Either the agent is over-permissioned up front, or it is blocked by manual ticketing loops every time reality changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Access packages for agent identities are the bridge
&lt;/h2&gt;

&lt;p&gt;This is where &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-access-packages" rel="noopener noreferrer"&gt;access packages for agent identities&lt;/a&gt; become much more than a governance checkbox.&lt;/p&gt;

&lt;p&gt;Access packages give you a permission supply chain. The agent does not invent access. It requests from a pre-governed catalog. Policy decides if, when, and how access is granted.&lt;/p&gt;

&lt;p&gt;That sounds abstract until you map it to day-to-day architecture decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identity engineers define packages that correspond to meaningful data capabilities.&lt;/li&gt;
&lt;li&gt;Security and compliance teams define who can approve under which conditions.&lt;/li&gt;
&lt;li&gt;Agent runtime requests package assignment only when task context justifies it.&lt;/li&gt;
&lt;li&gt;Lifecycle policy removes or expires access when the need window closes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly the governance direction reflected in &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/agent-id-governance-overview" rel="noopener noreferrer"&gt;Entra guidance for governing agent identities&lt;/a&gt;: agent access is not just about granting once, it is about ongoing controlled assignment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The underrated power move: put consent inside workflow
&lt;/h2&gt;

&lt;p&gt;Most teams still treat admin consent like a one-off privileged ceremony. Someone with rights clicks approve, everyone moves on, and the architecture diagram quietly lies about "least privilege."&lt;/p&gt;

&lt;p&gt;Access packages let you treat that approval as a workflow stage instead of an exception path.&lt;/p&gt;

&lt;p&gt;With entitlement management policies, you can require &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-approval-policy" rel="noopener noreferrer"&gt;multi-stage approvals&lt;/a&gt;, use &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-dynamic-approval" rel="noopener noreferrer"&gt;dynamic approval selection&lt;/a&gt;, enforce &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-incompatible" rel="noopener noreferrer"&gt;separation-of-duties with incompatible packages&lt;/a&gt;, and enforce &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-lifecycle-policy" rel="noopener noreferrer"&gt;expiry and lifecycle controls&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If that still feels too generic, add custom process hooks through &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-logic-apps-integration" rel="noopener noreferrer"&gt;Logic Apps integration for entitlement management&lt;/a&gt;. That is where you inject business-specific gates: risk score checks, change-ticket correlation, regulatory checks, or post-assignment notifications into your SOC workflow.&lt;/p&gt;

&lt;p&gt;This is why I keep calling access packages an underestimated powerhouse. They are not "just governance UI." They are programmable policy choreography.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this looks in a real request loop
&lt;/h2&gt;

&lt;p&gt;A transformational agent pattern becomes concrete when the request loop is concrete.&lt;/p&gt;

&lt;p&gt;Start with the assumption that the agent is under-permissioned for future unknown tasks. When it hits a boundary, it enters a governed escalation loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Determine the missing capability from the failed call and policy context.&lt;/li&gt;
&lt;li&gt;Discover candidate packages from &lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-list-accesspackages?view=graph-rest-1.0" rel="noopener noreferrer"&gt;GET access packages&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Inspect assignment rules through &lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-list-assignmentpolicies?view=graph-rest-1.0" rel="noopener noreferrer"&gt;GET assignment policies&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If policy allows, submit &lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-post-assignmentrequests?view=graph-rest-1.0" rel="noopener noreferrer"&gt;POST assignment request&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Let approval workflow, incompatibility checks, and lifecycle policy decide the final outcome.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you need to inspect package role mappings more deeply, you can also query &lt;a href="https://learn.microsoft.com/en-us/graph/api/accesspackage-list-resourcerolescopes?view=graph-rest-1.0" rel="noopener noreferrer"&gt;resource role scopes in an access package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Notice the key architectural boundary: the agent can &lt;em&gt;request&lt;/em&gt; escalation, but it cannot bypass governance. That is the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more than one Entra feature
&lt;/h2&gt;

&lt;p&gt;If we are honest, most early agent pilots still hide one uncomfortable truth: broad standing access was pre-granted so the demo would not fail in front of stakeholders.&lt;/p&gt;

&lt;p&gt;That shortcut does not scale. It becomes technical debt with legal exposure.&lt;/p&gt;

&lt;p&gt;The better model is plain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;capability discovery can be dynamic,&lt;/li&gt;
&lt;li&gt;approval can be policy-bound,&lt;/li&gt;
&lt;li&gt;access can be time-bound,&lt;/li&gt;
&lt;li&gt;accountability can be explicit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That combination is exactly what transformational agents need. They can evolve without becoming permanent over-privileged identities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision point for architecture teams
&lt;/h2&gt;

&lt;p&gt;If your operating model is "we will manually update permissions whenever the agent needs something new," you do not have an agent permission model. You have a backlog with production blast radius.&lt;/p&gt;

&lt;p&gt;If your operating model is "new access must flow through access packages with policy-owned approvals and expiry," then you have something that can survive beyond a pilot and withstand audit pressure.&lt;/p&gt;

&lt;p&gt;That is the shift in one sentence: agent autonomy should grow through governed workflow, not through standing privilege.&lt;/p&gt;

&lt;p&gt;This is why the "missing API Permissions tab" conversation is useful. It forces the right question. Not "where do I click to grant more?" but "what control plane governs permission growth in my tenant?"&lt;/p&gt;

&lt;p&gt;For Entra Agent ID in enterprise reality, the best answer today is access packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID key concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/authorization-agent-id" rel="noopener noreferrer"&gt;Authorization in Microsoft Entra Agent ID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/user-admin-consent-overview" rel="noopener noreferrer"&gt;Overview of user and admin consent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-user-consent?pivots=portal" rel="noopener noreferrer"&gt;Configure how users consent to applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-access-packages" rel="noopener noreferrer"&gt;Access packages for agent identities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/agent-id-governance-overview" rel="noopener noreferrer"&gt;Governing agent identities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-approval-policy" rel="noopener noreferrer"&gt;Configure approval policy for an access package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-dynamic-approval" rel="noopener noreferrer"&gt;Configure dynamic approvals in entitlement management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-incompatible" rel="noopener noreferrer"&gt;Configure separation of duties checks for access packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-lifecycle-policy" rel="noopener noreferrer"&gt;Change lifecycle settings for an access package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-logic-apps-integration" rel="noopener noreferrer"&gt;Trigger Logic Apps with custom extensions in entitlement management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-list-accesspackages?view=graph-rest-1.0" rel="noopener noreferrer"&gt;List access packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-list-assignmentpolicies?view=graph-rest-1.0" rel="noopener noreferrer"&gt;List assignment policies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-post-assignmentrequests?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Create access package assignment request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/accesspackage-list-resourcerolescopes?view=graph-rest-1.0" rel="noopener noreferrer"&gt;List resource role scopes in an access package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>entraagentid</category>
      <category>identitygovernance</category>
      <category>microsoftentra</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>Every change to an Entra extension is a Control Plane event: the monitoring contract</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Tue, 07 Jul 2026 09:47:00 +0000</pubDate>
      <link>https://dev.to/astaykov/every-change-to-an-entra-extension-is-a-control-plane-event-the-monitoring-contract-5621</link>
      <guid>https://dev.to/astaykov/every-change-to-an-entra-extension-is-a-control-plane-event-the-monitoring-contract-5621</guid>
      <description>&lt;p&gt;Parts 1 and 2 of this series (&lt;a href="https://dev.to/astaykov/microsoft-entra-extensibility-is-a-gift-it-is-also-control-plane-4egn"&gt;Microsoft Entra extensibility is a gift. It is also Control Plane.&lt;/a&gt; and &lt;a href="https://dev.to/astaykov/securing-the-code-that-decides-who-entra-trusts-a-function-app-and-a-logic-app-end-to-end-1bi0"&gt;Securing the code that decides who Entra trusts&lt;/a&gt;) made two static decisions. &lt;em&gt;Where&lt;/em&gt; the code lives: a dedicated Control Plane subscription, directly under the root management group or under a dedicated Control Plane management group, never in the platform identity subscription or an application landing zone. &lt;em&gt;What credential&lt;/em&gt; it uses to call out: a managed identity by default, &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;federated identity credentials&lt;/a&gt; when the call must leave Azure, certificates as a tolerated middle step, and static symmetric keys never.&lt;/p&gt;

&lt;p&gt;Both decisions are one-time. You make them, you walk away, you do not touch them for months.&lt;/p&gt;

&lt;p&gt;The third decision is not like that. It is continuous, and it is the one most teams quietly skip: how do you know the deployed code on that Function App is still the code your reviewers approved? How do you know the Logic App workflow definition has not been rewritten since last Tuesday? How do you know nobody added a federated identity credential to the managed identity at 3 a.m. on a Saturday?&lt;/p&gt;

&lt;p&gt;The answer is monitoring. Not "we have Log Analytics turned on." Monitoring with a specific operating contract attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  The posture inversion
&lt;/h2&gt;

&lt;p&gt;For most Azure workloads, the default operating posture is reasonable trust. Engineers deploy. Pipelines run. Configuration drifts a little. The team reviews changes weekly. Anomalies are caught eventually.&lt;/p&gt;

&lt;p&gt;For a Microsoft Entra extension, that posture is wrong. The default has to be inverted.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Once an Entra extension lands in production, every change to it is suspicious by default.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not "needs review." Not "let's check first." Suspicious. The default state of an alert firing on a Function App that hosts a &lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;custom claims provider&lt;/a&gt; is "the SOC is investigating, prove this was approved." If you cannot prove the change was approved within the team's response SLA, the change is treated as an incident and rolled back. That posture is harsh on purpose. The same RBAC inheritance chain that lets a Contributor four management groups above your Function App quietly replace its code (the central argument of Part 1) is what forces the inverted default. You cannot rely on the deployment surface to be small. You have to rely on the alerting surface to be loud.&lt;/p&gt;

&lt;p&gt;That inversion is the monitoring contract this article is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three change surfaces
&lt;/h2&gt;

&lt;p&gt;A production Entra extension has three change surfaces, and each one needs its own forced-diagnostics control, its own alert, and its own row on the operating contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  Surface 1: the runtime itself
&lt;/h3&gt;

&lt;p&gt;This is the surface most teams think of first, and the one most teams under-instrument. The deployed code on the Function App. The workflow definition on the Logic App. The App Settings. The environment variables. The runtime version. The configured custom domain. Each of these is a knob that, if turned, changes the behavior of the extension the next time Entra calls it.&lt;/p&gt;

&lt;p&gt;For the custom claims provider Function App, the relevant Azure Resource Manager operations to alert on are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.Web/sites/extensions/write&lt;/code&gt; (a new deployment was pushed).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.Web/sites/config/appsettings/write&lt;/code&gt; (App Settings were changed, including any reference to a Key Vault secret).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.Web/sites/config/web/write&lt;/code&gt; (runtime version, startup command, or general configuration was changed).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.Web/sites/publishxml/action&lt;/code&gt; (publish profile credentials were generated, which is one of the easiest ways to deploy code outside the normal pipeline).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the dynamic approval Logic App, the analogous operations are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.Logic/workflows/write&lt;/code&gt; (the workflow definition itself was modified).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.Logic/workflows/connections/write&lt;/code&gt; and &lt;code&gt;Microsoft.Web/connections/write&lt;/code&gt; (an API connection was created or modified, including the authentication target it points at).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these should be backed by an &lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/activity-log-alerts" rel="noopener noreferrer"&gt;Activity Log alert&lt;/a&gt; scoped to the Control Plane subscription, with an action group that routes to the SOC's primary intake. Not to the team's chat channel. Not to an email list. The SOC's intake.&lt;/p&gt;

&lt;h3&gt;
  
  
  Surface 2: identity and RBAC
&lt;/h3&gt;

&lt;p&gt;This is the surface that does not look like the extension at all and is therefore the easiest to ignore. The extension is unchanged. The blast radius around it is what changed.&lt;/p&gt;

&lt;p&gt;Specific things to alert on, across the Control Plane subscription:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.Authorization/roleAssignments/write&lt;/code&gt; anywhere on the inheritance path, from the resource up to the subscription. A Contributor (or User Access Administrator, or Owner) just appeared on a tier in the chain. Walk the inheritance (&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/overview" rel="noopener noreferrer"&gt;Azure RBAC overview&lt;/a&gt;) and ask: does this new principal now have effective Contributor on the Function App? If yes, the SOC needs to know.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write&lt;/code&gt; on any user-assigned managed identity in scope. A new &lt;a href="https://learn.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview?view=graph-rest-1.0" rel="noopener noreferrer"&gt;federated identity credential&lt;/a&gt; is, by construction, a new way to act as that identity from outside Azure. Treat it as a credential issuance event, because that is what it is.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.KeyVault/vaults/accessPolicies/write&lt;/code&gt; and &lt;code&gt;Microsoft.Authorization/roleAssignments/write&lt;/code&gt; scoped to the Key Vault. Same logic as the RBAC inheritance, sharper consequence: Owner on the Key Vault is operationally Owner of every certificate in it.&lt;/li&gt;
&lt;li&gt;App registration credential events in the Entra audit log. The Function App and the Logic App that back the extension are both fronted by app registrations or managed identities in Entra. A new client secret, certificate, or federated credential added to that app registration is an alert-worthy event, full stop. The &lt;a href="https://learn.microsoft.com/en-us/entra/identity/monitoring-health/concept-audit-logs" rel="noopener noreferrer"&gt;Entra audit logs&lt;/a&gt; capture these as &lt;code&gt;Update application – Certificates and secrets management&lt;/code&gt; events; pipe them into the same SOC intake.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Surface 3: the Entra-side binding
&lt;/h3&gt;

&lt;p&gt;This surface lives entirely in Entra, not in Azure. The custom claims provider is &lt;em&gt;bound&lt;/em&gt; to the application through a custom authentication extension configuration. The dynamic approval Logic App is &lt;em&gt;bound&lt;/em&gt; to an access package through an entitlement management custom extension. Those bindings are what make Entra actually call your code. Change the binding, and Entra now calls somebody else's code instead.&lt;/p&gt;

&lt;p&gt;Two specific events worth their own alerts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changes to custom authentication extensions in the Entra audit log: the endpoint URL was repointed, the API authentication configuration was changed, the extension was disabled.&lt;/li&gt;
&lt;li&gt;Changes to entitlement management custom extensions: a new callback URL, a new authentication method, a change to the access package policy that consumes the extension.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same Entra audit log feed that the IGA team already monitors covers most of this. The extra step is making sure the SOC sees it alongside the Azure Activity Log events, because the correlation between "the Entra binding moved" and "a deployment happened on the new target one hour earlier" is exactly the story you want analysts to be able to tell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forced diagnostics: making the signal undeniable
&lt;/h2&gt;

&lt;p&gt;Alerts only fire if the signal reaches the alert engine. Three controls turn diagnostics from "we enabled it on most resources" into a property of the subscription itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure Policy with &lt;code&gt;deployIfNotExists&lt;/code&gt; for diagnostic settings.&lt;/strong&gt; Apply &lt;a href="https://learn.microsoft.com/en-us/azure/governance/policy/concepts/effect-deploy-if-not-exists" rel="noopener noreferrer"&gt;built-in or custom policies&lt;/a&gt; at the Control Plane management group that force every Function App, every Logic App, every Key Vault, every Storage Account, and every Managed Identity created underneath it to ship diagnostic logs to a dedicated tenant-level &lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/diagnostic-settings" rel="noopener noreferrer"&gt;Log Analytics workspace&lt;/a&gt;. The policy is &lt;code&gt;deployIfNotExists&lt;/code&gt;, not &lt;code&gt;audit&lt;/code&gt;, so a missing diagnostic setting is repaired by the platform, not just reported on. There are existing built-ins covering Logic Apps and many resource types; custom definitions cover the rest. The principle is: it is not optional, and it is not possible to deploy a resource into this management group without diagnostic settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure Policy &lt;code&gt;deny&lt;/code&gt; for tampering with diagnostic settings.&lt;/strong&gt; A &lt;code&gt;deployIfNotExists&lt;/code&gt; policy creates the setting. A complementary policy denies its modification or removal by anyone except a tightly-scoped platform identity. If an engineer cannot turn the diagnostic setting off, an attacker who compromises that engineer cannot either.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource Locks on the resource groups that host the extensions.&lt;/strong&gt; &lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/lock-resources" rel="noopener noreferrer"&gt;Resource Locks&lt;/a&gt; at &lt;code&gt;CanNotDelete&lt;/code&gt; for everything, &lt;code&gt;ReadOnly&lt;/code&gt; for the resource groups that hold the runtime resources, applied at the resource-group level. ReadOnly does not prevent code deployments through the Function App's own publish endpoint, so it is not a substitute for the alert on &lt;code&gt;Microsoft.Web/sites/extensions/write&lt;/code&gt;, but it does block the entire class of "an attacker recreates the resource with the same name and a different definition" attack.&lt;/p&gt;

&lt;p&gt;Layered: policy forces diagnostics on, policy prevents diagnostics from being turned off, resource locks prevent the resources from being deleted out from under the diagnostics, alerts on the resulting log stream surface every change. Each control compensates for the failure modes of the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Correlation: the story the SIEM has to be able to tell
&lt;/h2&gt;

&lt;p&gt;Each individual alert is signal. The value lives in the correlation across feeds. The SOC should be able to ask, and answer, questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A token issued by Entra at 14:07 carried a claim asserting "department=Finance." The custom claims provider for that application is hosted on Function App &lt;code&gt;fa-claims-prod&lt;/code&gt;. Did the deployed code on &lt;code&gt;fa-claims-prod&lt;/code&gt; change in the last 24 hours? Did its App Settings? Did any role assignment land on it, its resource group, its subscription, or any management group above it?&lt;/li&gt;
&lt;li&gt;An access package request was auto-approved at 09:21 for a privileged group. The dynamic approval Logic App that decided is &lt;code&gt;la-dynapproval-prod&lt;/code&gt;. Did the workflow definition change in the last 7 days? Did any of its API connections get repointed? Did the Logic App's managed identity get a new federated credential?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both questions are answerable with &lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/platform-logs-overview" rel="noopener noreferrer"&gt;Azure Activity Log&lt;/a&gt;, Entra audit log, Function App and Logic App resource logs, and the extension's own application logs, all sitting in one Log Analytics workspace, with &lt;a href="https://learn.microsoft.com/en-us/azure/sentinel/data-connectors/microsoft-entra-id" rel="noopener noreferrer"&gt;Microsoft Sentinel&lt;/a&gt; on top stitching them together. The Sentinel queries are the easy part. The hard part is making sure the three feeds are guaranteed to be there, which is exactly what the forced diagnostics controls deliver.&lt;/p&gt;

&lt;h2&gt;
  
  
  The operating contract: three states, not four
&lt;/h2&gt;

&lt;p&gt;Every alert from any of the three change surfaces lands in one of exactly three buckets. There is no fourth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approved change.&lt;/strong&gt; The deployment was pre-declared in the change management system. The change record carries the artifact hash, the pipeline run ID, the requesting engineer, and a declared start and end window. The alert correlates to the change record automatically (on pipeline run ID, on deployment principal, on time window) and is closed within minutes. The audit trail shows the alert, the correlation, and the closure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Informational platform change.&lt;/strong&gt; Microsoft platform-driven activity that you do not control: automatic certificate rotations on platform-managed components, Microsoft-side runtime version refreshes, Azure-managed identity key rotations, and similar. These still ship to the same workspace and still fire as Activity Log entries, but they route to a low-severity "platform" queue, not to the SOC's primary intake. Two rules govern this bucket: the events must be attributable to a known Microsoft service principal or platform operation (the actor identity on the Activity Log entry is non-human and matches an allow-listed Microsoft pattern), and the bucket must be reviewed at least weekly so it does not become a quiet hiding place. Anything that does not cleanly match a platform pattern falls through to the third bucket by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incident.&lt;/strong&gt; Anything that is neither pre-declared by a change record nor cleanly attributable to a Microsoft platform operation. SOC intake, paged on-call, automatic rollback if the runtime change can be reverted, manual investigation either way. The default reaction is to revert first and investigate after. The cost of a wrongly-reverted legitimate change is a Slack apology. The cost of a wrongly-allowed malicious change is a forged claim in a token your applications already trusted.&lt;/p&gt;

&lt;p&gt;That is the entire operating model. Approved, informational-platform, or incident. No "we will look at it later." No "probably the platform team." If it does not fit one of the first two buckets within a tight automatic correlation window, it is bucket three.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three-legged stool
&lt;/h2&gt;

&lt;p&gt;Part 1 placed the resources correctly. Part 2 made sure they authenticate without leaking secrets. Part 3 makes sure that, once they are running, every change to them is either justified or visibly investigated. None of the three legs stands alone. A correctly placed resource without monitoring is one quiet deployment away from being someone else's resource. A perfectly monitored resource using a static API key is monitoring around an already-compromised credential. A managed identity in the wrong subscription is a credential model wasted on an over-permissive blast radius.&lt;/p&gt;

&lt;p&gt;Built together, they are how Entra extensibility stays the thing that makes Entra a great product, rather than the thing that quietly hollowed it out. Use the extensibility. Put the code where it belongs. Authenticate it with the right credentials. And treat every change to it, from the first day it is in production, as a Control Plane event worth proving.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;Custom authentication extensions overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/diagnostic-settings" rel="noopener noreferrer"&gt;Diagnostic settings in Azure Monitor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/platform-logs-overview" rel="noopener noreferrer"&gt;Azure Monitor platform logs overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/governance/policy/concepts/effect-deploy-if-not-exists" rel="noopener noreferrer"&gt;Azure Policy &lt;code&gt;deployIfNotExists&lt;/code&gt; effect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/activity-log-alerts" rel="noopener noreferrer"&gt;Activity log alerts in Azure Monitor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-types" rel="noopener noreferrer"&gt;Azure Monitor alert types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/lock-resources" rel="noopener noreferrer"&gt;Lock your resources to protect your infrastructure (Resource Locks)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/monitoring-health/concept-audit-logs" rel="noopener noreferrer"&gt;Microsoft Entra audit logs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/sentinel/data-connectors/microsoft-entra-id" rel="noopener noreferrer"&gt;Microsoft Entra ID data connector for Microsoft Sentinel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Federated Identity Credentials overview (Microsoft Graph)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/overview" rel="noopener noreferrer"&gt;Azure RBAC overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;Workload Identity Federation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>microsoftentra</category>
      <category>azuremonitor</category>
      <category>zerotrust</category>
      <category>secops</category>
    </item>
    <item>
      <title>Securing the code that decides who Entra trusts: a Function App and a Logic App, end to end</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Thu, 02 Jul 2026 10:37:00 +0000</pubDate>
      <link>https://dev.to/astaykov/securing-the-code-that-decides-who-entra-trusts-a-function-app-and-a-logic-app-end-to-end-1bi0</link>
      <guid>https://dev.to/astaykov/securing-the-code-that-decides-who-entra-trusts-a-function-app-and-a-logic-app-end-to-end-1bi0</guid>
      <description>&lt;p&gt;Part 1 of this series, [[Entra-Extensibility-Is-Control-Plane]], made the case that every Microsoft Entra extension point hands a piece of the Entra trust boundary to a system Entra does not own. The Azure resources that host that code sit on the Control Plane (in the modern Microsoft &lt;a href="https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model" rel="noopener noreferrer"&gt;Enterprise Access Model&lt;/a&gt;, what the legacy tiered model called Tier 0). The Azure RBAC inheritance chain makes them dangerously easy to compromise from far up the management-group tree, and they deserve a placement and a guardrail set normally reserved for domain controllers and Entra Connect.&lt;/p&gt;

&lt;p&gt;This article gets concrete. Two real extension scenarios, end to end, and then the question that decides the security of both: what credential does the extension use when it calls out?&lt;/p&gt;

&lt;h2&gt;
  
  
  Example A: a custom claims provider backed by an Azure Function
&lt;/h2&gt;

&lt;p&gt;The first scenario is the one most likely to land in a production tenant in the next six months. A team needs to inject custom claims into the access tokens issued to their applications. The supported path is a &lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;custom claims provider&lt;/a&gt;, implemented as a REST endpoint that Entra calls during the token issuance event. The reference implementation is an Azure Function.&lt;/p&gt;

&lt;p&gt;The flow, in one paragraph. A user signs in to an application registered in Entra. Entra's token issuance pipeline reaches the configured custom claims provider extension. Entra calls the Function App's HTTPS endpoint with a server-to-server access token in the &lt;code&gt;Authorization&lt;/code&gt; header, exactly as documented in &lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;the step that covers protecting your Azure Function&lt;/a&gt;. The Function validates the incoming token (issuer, audience, signature), inspects the request body, calls whatever upstream sources it needs to resolve the claims it cares about, and returns a JSON response describing which claims to add to the outgoing token. Entra builds the access token, including the returned claims, and hands it to the relying application. The application makes authorization decisions based on those claims.&lt;/p&gt;

&lt;p&gt;Read that one more time. &lt;em&gt;The application makes authorization decisions based on those claims.&lt;/em&gt; The Function App controls what your applications see. A compromised Function App is, in practical terms, a claim forger sitting inside your token issuance pipeline. Whatever an attacker can put in a returned claim, the downstream application will trust as if Entra had asserted it.&lt;/p&gt;

&lt;p&gt;The blast radius of that Function App is therefore the union of everything that can change what code runs in it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The source repository. Branch protection, code-owner approvals, the list of users with push rights to &lt;code&gt;main&lt;/code&gt;, the list of users with admin rights on the repository who can bypass protection, and every CI configuration file that ships with the repo.&lt;/li&gt;
&lt;li&gt;The CI/CD pipeline definition. Who can edit it, who can re-run it with arbitrary inputs, who can change which artifact gets deployed at the end of a run.&lt;/li&gt;
&lt;li&gt;The identity the pipeline uses to deploy to Azure. This is the credential that lets the pipeline rewrite the Function App's code at any time. If that credential is a client secret stored as a CI variable, the Function App's code is one leaked variable away from being replaced.&lt;/li&gt;
&lt;li&gt;The Function App resource itself, and every security principal that has Website Contributor, Contributor, or Owner on it directly. These principals can replace the deployed ZIP without ever touching the repository.&lt;/li&gt;
&lt;li&gt;The resource group, the subscription, every management group above the subscription, and the root. As &lt;a href="https://dev.to/astaykov/microsoft-entra-extensibility-is-a-gift-it-is-also-control-plane-4egn"&gt;Part 1&lt;/a&gt; walked, Contributor at any level inherits down. A Contributor (any role) on the root management group does not need to be a member of your identity team to replace your Function App's code.&lt;/li&gt;
&lt;li&gt;The Key Vault holding any secrets, certificates, or connection strings the Function uses to talk to upstream systems. Owner on that Key Vault is, for practical purposes, Owner on the Function's ability to authenticate outbound.&lt;/li&gt;
&lt;li&gt;The App Service Plan, because deployment slots, scaling rules, and runtime versions sit at that scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A real custom claims provider in production has to harden every item in that list. Missing any one of them is enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example B: a Logic App backing dynamic approval for an access package
&lt;/h2&gt;

&lt;p&gt;The second scenario is governance-shaped. An access package in &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-logic-apps-integration" rel="noopener noreferrer"&gt;Microsoft Entra entitlement management&lt;/a&gt; is configured to use &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-dynamic-approval" rel="noopener noreferrer"&gt;dynamic approval&lt;/a&gt;, so that the approver of a request is selected at runtime by an Azure Logic App rather than statically declared in the policy.&lt;/p&gt;

&lt;p&gt;The flow. A user requests assignment to the access package. Entitlement management invokes the configured Logic App, passing context about the requestor and the package. The Logic App runs whatever workflow you have authored. Typically that workflow needs to call Microsoft Graph (to resolve the requestor's manager, project assignment, or group membership) and at least one external system (a leave or vacation calendar, a shift roster, an IT change management board, a project allocation tool). The Logic App returns the identity of the human or group who should approve, or in some variants it short-circuits and returns an approval or denial directly. Entitlement management then routes the request accordingly.&lt;/p&gt;

&lt;p&gt;The Logic App is now part of your access governance. If an attacker can rewrite the workflow, the attacker can name themselves as the approver for any access package that uses this dynamic approval policy. Or worse: rewrite the workflow to return "auto-approve" for a specific requestor and never invoke a human at all.&lt;/p&gt;

&lt;p&gt;Most of the Function App blast-radius list applies here too, with one extra wrinkle. A Logic App often has fewer source-code artifacts (the workflow can be authored directly in the portal, although &lt;a href="https://learn.microsoft.com/en-us/azure/logic-apps/create-standard-workflows-visual-studio-code" rel="noopener noreferrer"&gt;authoring it through a code project under source control&lt;/a&gt; is strongly recommended for exactly the reasons we are discussing). What a Logic App always has, in abundance, is &lt;em&gt;connections&lt;/em&gt;. The Microsoft Graph connection, the SharePoint connection, the HTTP connector pointing at the change-management API, the Salesforce connection for project data. Each connection is a credential the Logic App will use, and each credential is something an attacker would happily inherit if they took ownership of the Logic App resource. The connection objects themselves are Azure resources in the same resource group, subject to the same RBAC inheritance chain.&lt;/p&gt;

&lt;p&gt;The surface is broader than the Function App's. The principle is the same. The Logic App is Control Plane because of who calls it and what its answer is used for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The credential ladder
&lt;/h2&gt;

&lt;p&gt;Both examples force the same question. Once your code is running, what does it use to authenticate when it calls downstream? Microsoft Graph, the corporate HR system, a SharePoint list, an external SaaS API. Pick one. There are three honest answers, and they are not equivalent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static keys: assume already compromised
&lt;/h3&gt;

&lt;p&gt;A static API key, or the symmetric &lt;code&gt;client_id&lt;/code&gt; plus &lt;code&gt;client_secret&lt;/code&gt; pair, is the least secure credential you can use, and you should treat it as already compromised. That is not hyperbole and it is not a "best practice" framing. It is the structural reality.&lt;/p&gt;

&lt;p&gt;You did not pick the entropy. You do not know who pasted it into a chat window during an incident three years ago. You do not know whether the developer who first received it stored a copy in their personal note-taking app. You do not know whether the CI variable holding it was visible to the build agent's logs at some point during a regression. You do not know whether the rotation calendar reminder fired, and you do not know whether the previous value was scrubbed from every place it was ever stored.&lt;/p&gt;

&lt;p&gt;For non-critical workloads, this is a manageable risk. For code that decides what claims your applications see, or who approves access to your most sensitive packages, it is not. If your Control Plane Entra extensions are still authenticating outbound with static symmetric credentials, the rest of your Zero Trust program is theater for that path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Certificates: better, but only as strong as their issuance and storage
&lt;/h3&gt;

&lt;p&gt;Certificate-based authentication is genuinely a step up. The credential is asymmetric, the private key never has to leave the host that uses it, and the rotation story is cleaner. The honest assessment, though, is that a certificate is only as secure as the process that produces, transports and stores it.&lt;/p&gt;

&lt;p&gt;Be specific about the questions a certificate forces you to answer. How was the certificate issued: by a managed PKI, by your tenant's own CA, by a developer with &lt;code&gt;openssl&lt;/code&gt; at a laptop? How did the public key end up in the Entra app registration credentials: a portal upload by a human, a pipeline call to Microsoft Graph, a manual step in a runbook? Where is the private key stored: on the host filesystem, in an HSM, in a Key Vault? If it is in Key Vault, is it &lt;a href="https://learn.microsoft.com/en-us/azure/key-vault/certificates/about-certificates" rel="noopener noreferrer"&gt;non-exportable&lt;/a&gt;, or did someone tick the wrong box when they imported it? Was the certificate generated &lt;em&gt;inside&lt;/em&gt; the Key Vault, or was it generated elsewhere and imported, in which case the original private key existed somewhere outside the HSM at least once?&lt;/p&gt;

&lt;p&gt;And then the question Part 1 of this series spent an entire section on: who has Owner on that Key Vault? Walk the &lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/overview" rel="noopener noreferrer"&gt;Azure RBAC inheritance chain&lt;/a&gt; from the Key Vault up through its resource group, its subscription, its management groups, and the root. Every Owner along that chain is, for practical purposes, an Owner of every certificate in that Key Vault. The certificate is not as static as a symmetric key, but the principals who can extract or replace it follow the same inheritance rules every other Azure resource follows.&lt;/p&gt;

&lt;p&gt;A certificate in a Key Vault inside a wide-RBAC subscription is, operationally, not very different from a static key with extra steps. The credential improved. The principal model around it did not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managed Identities: the right baseline
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview" rel="noopener noreferrer"&gt;managed identity&lt;/a&gt; is the right baseline for any Entra extension hosted on Azure compute. The platform manages the credential. The compute resource (Function App, Logic App, App Service, container) requests an access token from a local metadata endpoint. Entra issues it. No human, no pipeline, no developer ever sees a secret.&lt;/p&gt;

&lt;p&gt;When the call has to leave Azure, &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;Workload Identity Federation&lt;/a&gt; extends the same pattern across trust boundaries. A managed identity can act as the credential for an Entra app registration through a federated identity credential, and an Entra-issued token can be exchanged for an external system's token as long as that system supports the &lt;a href="https://www.rfc-editor.org/rfc/rfc7523" rel="noopener noreferrer"&gt;OpenID Connect / RFC 7523&lt;/a&gt; pattern. The longer treatment of how this composes for AI agent platforms is in &lt;a href="https://dev.to/astaykov/your-agentic-platform-doesnt-need-a-single-secret-managed-identities-workload-identity-3602"&gt;Your agentic platform doesn't need a single secret&lt;/a&gt;, and most of the same building blocks apply when the workload happens to be an Entra extension instead of an agent runtime.&lt;/p&gt;

&lt;p&gt;Even the right answer comes with its own discipline. A managed identity is not a free pass. Two specific guardrails matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System-assigned by default.&lt;/strong&gt; A system-assigned managed identity is lifecycle-bound to a single Azure resource. Delete the resource, the identity is gone. Replace the resource, the new instance gets a brand-new identity that must be re-granted permissions. That friction is the whole point. It makes the credential and the resource indistinguishable, which is exactly what you want for a Control Plane workload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-assigned managed identities are subscription-scoped reusable identities.&lt;/strong&gt; A user-assigned MI lives in a resource group and can be attached to any number of resources in the same tenant. That convenience is also a risk. Any Contributor on a resource in the same subscription can attach the same managed identity to a &lt;em&gt;new&lt;/em&gt; resource of their choosing, and that new resource can now act as the privileged caller into Microsoft Graph. Treat user-assigned MIs that hold real downstream permissions as Control Plane objects of their own, place them in the same dedicated Control Plane subscription as the workloads that use them, and never share one across planes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a managed identity is placed correctly, on a Control Plane resource, in a Control Plane subscription, under a Control Plane management group, the answer to "who can use this credential against Microsoft Graph" collapses to "exactly the workloads I deployed there, and exactly the principals who have rights to deploy to that subscription." That is the credential model these extensions deserve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting the two halves together
&lt;/h2&gt;

&lt;p&gt;Part 1 of this series argued that Entra extensions belong on the Control Plane because of what they decide. This article argued that the security of those decisions is the security of the smallest detail underneath them: the source repository, the pipeline identity, the runtime principal model, the credential the runtime uses to call out, the Key Vault that backs it, the RBAC inheritance above all of them.&lt;/p&gt;

&lt;p&gt;There is a uniform answer to the placement question. The Function App, the Logic App, the Key Vault, the user-assigned managed identities, the connections, the API connectors all belong in a dedicated Control Plane subscription under a dedicated Control Plane management group, directly under the root. Not in the platform identity subscription, not in a shared services subscription, not in an application landing zone. The list of principals with Contributor or Owner anywhere on the chain above those resources has to be short, audited, and reviewed on a cadence shorter than your access-review cycle.&lt;/p&gt;

&lt;p&gt;There is a uniform answer to the credential question too. The default credential for a Control Plane Entra extension is a managed identity, scoped tightly, lifecycle-bound where possible, system-assigned where possible, with &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;federated identity credentials&lt;/a&gt; covering the cases where the call has to leave Azure. Certificates are a tolerated middle step when the call truly has nowhere else to go. Static symmetric keys are not an option for code that influences Entra decisions, full stop.&lt;/p&gt;

&lt;p&gt;Use the extensibility. It is what makes Entra a great product, and the next year will keep adding new hooks worth using. Just host the code behind those hooks the same way you host the things Entra is protecting. The point of a Zero Trust enforcement engine is undermined the moment its decisions are shaped by code anyone can quietly replace.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;Custom authentication extensions overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-logic-apps-integration" rel="noopener noreferrer"&gt;Entitlement management Logic Apps integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-dynamic-approval" rel="noopener noreferrer"&gt;Externally determine the approval requirements for an access package using custom extensions (dynamic approval)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview" rel="noopener noreferrer"&gt;Managed identities for Azure resources overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;Workload Identity Federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/key-vault/certificates/about-certificates" rel="noopener noreferrer"&gt;About Azure Key Vault certificates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/overview" rel="noopener noreferrer"&gt;Azure RBAC overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/logic-apps/create-standard-workflows-visual-studio-code" rel="noopener noreferrer"&gt;Create a Standard logic app workflow with Visual Studio Code (source-controlled authoring)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc7523" rel="noopener noreferrer"&gt;RFC 7523: JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model" rel="noopener noreferrer"&gt;Enterprise Access Model (Control Plane / Management Plane)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>microsoftentra</category>
      <category>managedidentity</category>
      <category>identitygovernance</category>
      <category>zerotrust</category>
    </item>
    <item>
      <title>Microsoft Entra extensibility is a gift. It is also Control Plane.</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Tue, 30 Jun 2026 09:17:00 +0000</pubDate>
      <link>https://dev.to/astaykov/microsoft-entra-extensibility-is-a-gift-it-is-also-control-plane-4egn</link>
      <guid>https://dev.to/astaykov/microsoft-entra-extensibility-is-a-gift-it-is-also-control-plane-4egn</guid>
      <description>&lt;p&gt;Microsoft Entra is the Zero Trust policy enforcement engine sitting at the intersection of identities, endpoints, AI agents, networks and data. Every conversation about Conditional Access, every Privileged Identity Management workflow, every access package review, every token issued to an application or an agent: it all funnels through Entra. That is the entire point of the product, and that is why so much of the security industry's energy is spent hardening it.&lt;/p&gt;

&lt;p&gt;The most interesting thing happening to Entra right now is not a new policy type. It is &lt;em&gt;extensibility&lt;/em&gt;. In the last few years Entra has quietly become one of the most extensible identity platforms in the enterprise market. &lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;Custom authentication extensions&lt;/a&gt; let your code shape token issuance and authentication events. &lt;a href="https://learn.microsoft.com/en-us/entra/identity/authentication/how-to-authentication-external-method-manage" rel="noopener noreferrer"&gt;External authentication methods&lt;/a&gt; plug third-party MFA providers into the sign-in pipeline. &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/privileged-identity-management-custom-extensions" rel="noopener noreferrer"&gt;PIM custom extensions&lt;/a&gt; let your business logic approve or deny privileged role activation. &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/lifecycle-workflow-extensibility" rel="noopener noreferrer"&gt;Lifecycle workflow custom task extensions&lt;/a&gt; let your code influence whether an employee account is enabled, disabled, or transformed. Entitlement management talks to &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-logic-apps-integration" rel="noopener noreferrer"&gt;Logic Apps for governance workflows&lt;/a&gt;, and a specific variant, &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-dynamic-approval" rel="noopener noreferrer"&gt;dynamic approval&lt;/a&gt;, lets your code decide &lt;em&gt;who&lt;/em&gt; approves an access package request, or whether the request should be approved at all. More extension points are coming. The trend line is obvious.&lt;/p&gt;

&lt;p&gt;This is genuinely good. Identity decisions are business decisions, and business logic belongs in code your business writes. Extensibility is what turns Entra from a fixed product into a programmable enforcement engine, and that is the right direction.&lt;/p&gt;

&lt;p&gt;It is also the part where the security conversation almost always stops.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reframe nobody wants to write
&lt;/h2&gt;

&lt;p&gt;Every extension point hands a piece of the Entra trust boundary to a system Entra does not own. The decision is still announced from Entra. The &lt;em&gt;signal&lt;/em&gt; that drives the decision is shaped somewhere else. That somewhere else is now Control Plane, in the language of Microsoft's current &lt;a href="https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model" rel="noopener noreferrer"&gt;Enterprise Access Model&lt;/a&gt; (what the legacy tiered administration model used to call Tier 0). Control Plane is the set of systems that grant access to everything else: the directory itself, the privileged groups inside it, and now, by extension, any code that shapes a directory decision at runtime.&lt;/p&gt;

&lt;p&gt;Sit with the implications for a minute, scenario by scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/privileged-identity-management-custom-extensions" rel="noopener noreferrer"&gt;PIM custom extension&lt;/a&gt; can influence whether an identity gets a high-privilege role activated, in milliseconds, with no human in the loop. The endpoint that responds to PIM is now part of your privileged-access path.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/lifecycle-workflow-extensibility" rel="noopener noreferrer"&gt;lifecycle workflow custom task extension&lt;/a&gt; can be the anchor that decides whether a leaver's account is actually disabled tomorrow morning. The code that answers that workflow call is now part of your joiner-mover-leaver process.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-dynamic-approval" rel="noopener noreferrer"&gt;Logic App driving dynamic approval&lt;/a&gt; can decide who is allowed to approve a request for a sensitive access package, or whether the request gets pre-approved with no human reviewer at all. The Logic App is now part of your access governance.&lt;/li&gt;
&lt;li&gt;An Azure Function backing a &lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;custom claims provider&lt;/a&gt; can inject custom claims into the access tokens your applications consume. The Function is now part of your token issuance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of those endpoints is a Control Plane system. Not "important." Not "in scope for the next pentest." Control Plane. The same category you reserve for your domain controllers, your Entra Connect server, your root CA, and the accounts that can write to any of them.&lt;/p&gt;

&lt;p&gt;Most security writing about Entra extensibility focuses on the Entra side: how to register the extension, what scopes it needs, how the audit log captures the call. That work is necessary and well covered. The Azure side, where the actual code runs, is barely covered at all. That is the gap I want to close.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cloud Adoption Framework already saw half of this
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/overview" rel="noopener noreferrer"&gt;Azure Cloud Adoption Framework&lt;/a&gt; and the &lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/" rel="noopener noreferrer"&gt;Azure landing zones&lt;/a&gt; reference architecture do something deliberate: they split &lt;em&gt;platform&lt;/em&gt; landing zones from &lt;em&gt;application&lt;/em&gt; landing zones, and inside platform they carve out a dedicated &lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access" rel="noopener noreferrer"&gt;identity subscription&lt;/a&gt; for identity-related infrastructure. The &lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" rel="noopener noreferrer"&gt;subscription organization guidance&lt;/a&gt; treats identity as its own thing, not as a workload that shares a subscription with marketing analytics.&lt;/p&gt;

&lt;p&gt;That is exactly the right instinct. The problem is that the identity subscription is almost always described as the home of legacy identity infrastructure: Active Directory Domain Services domain controllers, Entra Connect, a Privileged Access Workstation jump box, maybe a few related VMs. It is described as the place where the &lt;em&gt;identity infrastructure that runs in Azure&lt;/em&gt; lives.&lt;/p&gt;

&lt;p&gt;It is not yet described as the place where the &lt;em&gt;Azure compute that influences Entra decisions at runtime&lt;/em&gt; lives. That is a different category, and it did not really exist five years ago in the volume it exists now. A landing zone designed in 2021 was not built to host the Function App behind your custom claims provider, the Logic App behind your dynamic approval policy, the queue-triggered Function that decides whether a lifecycle workflow disables an account. None of that was a workload pattern then.&lt;/p&gt;

&lt;p&gt;It is now. And those workloads are at least as sensitive as Entra Connect, because they execute on every relevant identity event, and a successful tamper does not generate the noisy reconfiguration footprint that touching Entra Connect would generate. They are quieter and at least as powerful.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Azure RBAC inheritance chain is the trap
&lt;/h2&gt;

&lt;p&gt;Here is the part of the picture that does not get said out loud enough. &lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/overview" rel="noopener noreferrer"&gt;Azure role-based access control&lt;/a&gt; inherits top-down, and the inheritance is unbreakable. A role assignment at a resource, resource group, subscription, &lt;a href="https://learn.microsoft.com/en-us/azure/governance/management-groups/overview" rel="noopener noreferrer"&gt;management group&lt;/a&gt;, or the tenant root management group flows downward to every resource underneath. Contributor at the resource group flows to the resource. Contributor at the subscription flows to every resource group in it. Contributor at the management group flows to every subscription. Contributor at the root management group flows to &lt;em&gt;everything&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This is fine for most workloads.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;It is corrosive for workloads that influence Entra decisions.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence is the entire argument of this article. Read it once more. The same RBAC model that makes Azure pleasant to operate at scale is the model that lets a Contributor four management groups above your Function App quietly become the author of the claims your applications trust. There is no Entra-side hardening that fixes this. There is no Conditional Access policy that fixes this. The fix is structural, and it lives in Azure.&lt;/p&gt;

&lt;p&gt;Picture an organization with a moderately mature Azure footprint. There is a platform management group, an application management group, a couple of regional management groups, a Sandbox management group, a Production management group. The custom claims provider Function App lives in a shared "platform services" subscription because that is where the platform team puts platform things. Now ask the inheritance question: who is Contributor on that subscription? Who is Contributor on its parent management group? Who is Contributor on the root? In most organizations the answer is "more people than you think, and at least one service principal you forgot about." Any one of them can replace the deployed code on that Function App. They do not need to touch the source repository. They do not need to break the CI/CD pipeline. They just deploy a new ZIP. The next time Entra calls your custom claims provider, it is calling their code.&lt;/p&gt;

&lt;p&gt;Source-control hardening is necessary and frequently celebrated. It is also not sufficient on its own, because Entra does not invoke your repository. Entra invokes the runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where these resources actually belong
&lt;/h2&gt;

&lt;p&gt;My direct take. The Azure resources that host code which influences Entra decisions are Control Plane resources. They belong either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;directly under the &lt;strong&gt;root management group&lt;/strong&gt;, in a dedicated subscription that exists for exactly this purpose, or&lt;/li&gt;
&lt;li&gt;one level deeper, under a dedicated &lt;strong&gt;Control Plane management group&lt;/strong&gt; that itself sits directly under the root.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not deeper. Not in the platform identity subscription where your domain controllers live. Not in a shared services subscription. Not in an application landing zone, ever. The blast radius of "any Contributor anywhere on the inheritance path can swap the runtime" forces the resources up the tree, into a place where the list of principals with write rights is short, audited, and reviewed.&lt;/p&gt;

&lt;p&gt;That choice has follow-on consequences. Resources at the top of the hierarchy do not benefit from the policies and guardrails the landing zone reference architecture applies further down. The dedicated Control Plane management group needs its own policy set: deny-by-default network rules, mandatory diagnostic settings to a tenant-level log analytics workspace, deny-create policies for everything except the resource types you actually need, and Resource Locks at the resource group level that survive the people who set them. Pinning these things at the top of the tree means designing them at the top of the tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  The questions you must be able to answer
&lt;/h2&gt;

&lt;p&gt;Before any Entra extension goes into production, the team that owns it has to be able to answer each of these without hedging:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who controls the source code? Specifically, who has push rights on the protected branch, who can bypass branch protection, and who can approve a pull request?&lt;/li&gt;
&lt;li&gt;Who controls the CI/CD pipeline? Who can edit the pipeline definition? Who can re-run a failed deployment with a different artifact?&lt;/li&gt;
&lt;li&gt;What identity does the pipeline run as when it deploys to Azure? If it is a service principal with a client secret or a stored certificate, treat that credential as already known to the threat actor.&lt;/li&gt;
&lt;li&gt;Who can directly replace the runtime, bypassing source and pipeline entirely? Walk the full RBAC inheritance chain from the resource up to the root, including every group, service principal, and managed identity with Contributor, Owner, or User Access Administrator.&lt;/li&gt;
&lt;li&gt;Where do the credentials this extension uses to call downstream systems live? Who has Owner on that Key Vault? Walk the inheritance chain again.&lt;/li&gt;
&lt;li&gt;Does the extension run with a system-assigned managed identity, a user-assigned managed identity shared with other workloads, a certificate in a Key Vault, or a client secret? Each answer has a different blast radius.&lt;/li&gt;
&lt;li&gt;How fast can you detect that the deployed code on the Function App or the deployed logic on the Logic App has changed? How fast can you detect that a role assignment was created on the hosting subscription or one of its parents?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of those questions is uncomfortable, the extension is not yet ready to be invoked by Entra in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;The two scenarios I want to walk in detail are a &lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;custom claims provider&lt;/a&gt; backed by an Azure Function and a &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-dynamic-approval" rel="noopener noreferrer"&gt;dynamic approval Logic App&lt;/a&gt; backing an entitlement management access package. Both are concrete. Both are increasingly common. Both expose the entire chain: source repository, pipeline identity, runtime resource, hosting subscription, RBAC inheritance, downstream credentials, Key Vault, the lot.&lt;/p&gt;

&lt;p&gt;And both lead into a question that deserves a fair, opinionated answer: what credential should that code use when it has to call back into Microsoft Graph or out to an external system? Static API key, certificate, or managed identity? Each option has a real failure mode and a real guardrail. The right answer is rarely the convenient one.&lt;/p&gt;

&lt;p&gt;That is the subject of the next article in this series. Where Part 1 makes the case that Entra extensibility is Control Plane, Part 2 will walk the two examples end to end and grade the credential ladder beneath them. Watch this space.&lt;/p&gt;

&lt;p&gt;The goal of this series is not to talk anyone out of using Entra extensibility. The opposite. Use it. It is what makes Entra a great product. Just host the code that influences Entra decisions the same way you host the things Entra is protecting.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/custom-extension-overview" rel="noopener noreferrer"&gt;Custom authentication extensions overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/authentication/how-to-authentication-external-method-manage" rel="noopener noreferrer"&gt;Manage an external authentication method in Microsoft Entra ID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/privileged-identity-management-custom-extensions" rel="noopener noreferrer"&gt;PIM custom extensions for role activation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/lifecycle-workflow-extensibility" rel="noopener noreferrer"&gt;Lifecycle workflow extensibility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-logic-apps-integration" rel="noopener noreferrer"&gt;Entitlement management Logic Apps integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-dynamic-approval" rel="noopener noreferrer"&gt;Externally determine approval requirements for an access package using custom extensions (dynamic approval)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/overview" rel="noopener noreferrer"&gt;Azure Cloud Adoption Framework overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/" rel="noopener noreferrer"&gt;Azure landing zones&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" rel="noopener noreferrer"&gt;Landing zone subscription organization and governance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access" rel="noopener noreferrer"&gt;Landing zone identity and access management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/role-based-access-control/overview" rel="noopener noreferrer"&gt;Azure RBAC overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/governance/management-groups/overview" rel="noopener noreferrer"&gt;Azure management groups&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model" rel="noopener noreferrer"&gt;Enterprise Access Model (Control Plane / Management Plane)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>microsoftentra</category>
      <category>zerotrust</category>
      <category>identitygovernance</category>
      <category>cloudadoptionframework</category>
    </item>
    <item>
      <title>One identity, two clouds: an AWS-hosted agent that authorizes with Microsoft Entra Agent ID</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Tue, 23 Jun 2026 09:23:00 +0000</pubDate>
      <link>https://dev.to/astaykov/one-identity-two-clouds-an-aws-hosted-agent-that-authorizes-with-microsoft-entra-agent-id-2bkl</link>
      <guid>https://dev.to/astaykov/one-identity-two-clouds-an-aws-hosted-agent-that-authorizes-with-microsoft-entra-agent-id-2bkl</guid>
      <description>&lt;p&gt;There is a quiet assumption baked into most identity conversations, and it usually goes unstated because everyone in the room already believes it: Microsoft identity is for Microsoft resources, and you run it on Microsoft infrastructure. Both halves feel so obvious that nobody bothers to test them.&lt;/p&gt;

&lt;p&gt;So I tested them. I built a proof-of-concept where an AI agent runs entirely on AWS, holds its own Microsoft Entra Agent ID, and uses that single identity to authorize calls to resources on &lt;em&gt;both&lt;/em&gt; sides of the cloud boundary: a Microsoft service and an AWS Lambda. The agent never touches Azure compute. The Lambda never sees an AWS credential on the call. And nothing about it required a special bridge, because the bridge already exists and it is called OAuth.&lt;/p&gt;

&lt;p&gt;The sample is &lt;a href="https://github.com/astaykov/agentid-agentcore" rel="noopener noreferrer"&gt;astaykov/agentid-agentcore&lt;/a&gt;. This is the walkthrough of why it works, written for the architect whose first reaction to "Microsoft Entra in my AWS stack" is a raised eyebrow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of it, stated plainly
&lt;/h2&gt;

&lt;p&gt;A browser single-page app signs the user in with &lt;a href="https://learn.microsoft.com/entra/identity-platform/msal-overview" rel="noopener noreferrer"&gt;MSAL.js&lt;/a&gt; and hands the resulting access token to an agent. The agent is hosted on &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agents-tools-runtime.html" rel="noopener noreferrer"&gt;AWS Bedrock AgentCore Managed Runtime&lt;/a&gt;, a fully managed runtime for agents. Inside that runtime, the agent acts &lt;em&gt;on behalf of the signed-in user&lt;/em&gt; against two downstream resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an &lt;strong&gt;AWS Lambda&lt;/strong&gt;, fronted by an API Gateway HTTP API (the PoC calls it the Echo API), and&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;&lt;a href="https://learn.microsoft.com/graph/mcp-server/get-started" rel="noopener noreferrer"&gt;Microsoft MCP Server for Enterprise&lt;/a&gt;&lt;/strong&gt;, the Microsoft-hosted tool surface over Microsoft Graph.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
  ↓  sign-in (MSAL.js)
Browser SPA
  ↓  Entra access token  [Bearer, header-only]
AgentCore Managed Runtime  ── hosted on AWS, holds an Entra Agent ID
  ├─→  AWS Lambda  (API Gateway HTTP API, native JWT authorizer)
  └─→  Microsoft MCP server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read that topology again and notice what is &lt;em&gt;not&lt;/em&gt; in it. There is no Azure virtual machine, no Azure Container App, no Azure Function. The compute is 100% AWS. The identity is 100% Microsoft Entra. Those two facts are usually assumed to travel together. They do not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AWS resource is the whole point
&lt;/h2&gt;

&lt;p&gt;It would be an unremarkable demo if the agent only called Microsoft services. Of course a Microsoft identity opens Microsoft doors. The claim that actually needs proving is the other one: that a Microsoft Entra-issued token can open an &lt;em&gt;AWS&lt;/em&gt; door.&lt;/p&gt;

&lt;p&gt;So look closely at the Echo API. It is an &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop.html" rel="noopener noreferrer"&gt;AWS API Gateway v2 HTTP API&lt;/a&gt; in front of a Lambda function. Nothing about it is Microsoft. And its access control is a &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html" rel="noopener noreferrer"&gt;native API Gateway JWT authorizer&lt;/a&gt;, the AWS-built-in kind, configured with exactly two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an &lt;strong&gt;issuer&lt;/strong&gt; of &lt;code&gt;https://login.microsoftonline.com/{tenant}/v2.0&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;audience&lt;/strong&gt; equal to the Echo API's own app registration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the entire trust configuration. An AWS resource, gated by an AWS-native authorizer, that grants access only when presented with a token &lt;em&gt;minted by Microsoft Entra&lt;/em&gt; and bound to the signed-in user. No Cognito. No IAM SigV4 signing on that request. No custom Lambda authorizer doing bespoke validation. The AWS platform validates a Microsoft token because, to an OIDC-aware authorizer, Microsoft Entra is simply another standards-compliant issuer.&lt;/p&gt;

&lt;p&gt;This is the sentence I want the skeptical AWS architect to sit with: &lt;em&gt;your API Gateway already knows how to trust Microsoft Entra. You have not been told to think of it that way, but the capability has been there all along.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Same identity, the Microsoft side
&lt;/h2&gt;

&lt;p&gt;The same agent, carrying the same identity, also calls the Microsoft MCP server. One agent. One Entra Agent ID. Two destinations in two different clouds, each handed a token scoped to it, each validating that token on its own terms.&lt;/p&gt;

&lt;p&gt;This is what makes Entra Agent ID interesting as an identity layer rather than a Microsoft-only convenience. The agent is not "an AWS thing that occasionally phones Microsoft." It is a governed identity in Microsoft Entra (&lt;a href="https://learn.microsoft.com/entra/agent-id/what-is-microsoft-entra-agent-id" rel="noopener noreferrer"&gt;an agent identity created from a blueprint&lt;/a&gt;) that happens to be hosted on AWS, and it reaches whatever it is authorized to reach regardless of which cloud the resource lives in. Microsoft's own documentation is explicit that &lt;a href="https://learn.microsoft.com/entra/agent-id/what-is-microsoft-entra-agent-id" rel="noopener noreferrer"&gt;Entra Agent ID works with agents built on non-Microsoft platforms, AWS Bedrock among them&lt;/a&gt;. The PoC is just that statement made concrete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this should land for an AWS architect
&lt;/h2&gt;

&lt;p&gt;The instinct to distrust cross-vendor identity is healthy, because most of it historically meant proprietary glue: a connector, an SDK shim, a sync job that copied identities from one directory into another and drifted out of band within a quarter. None of that is happening here.&lt;/p&gt;

&lt;p&gt;What is happening is plain OAuth 2.0 and OpenID Connect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ The AWS authorizer trusts an &lt;strong&gt;OIDC issuer&lt;/strong&gt;. Entra publishes standard OIDC discovery metadata; the authorizer validates &lt;code&gt;iss&lt;/code&gt;, &lt;code&gt;aud&lt;/code&gt;, and signature against it. This is the same mechanism you would use to trust any external IdP.&lt;/li&gt;
&lt;li&gt;✅ The agent acquires &lt;strong&gt;resource-scoped, user-bound tokens&lt;/strong&gt; through a standard &lt;a href="https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow" rel="noopener noreferrer"&gt;on-behalf-of style exchange&lt;/a&gt;. The user's sign-in is turned into a token audienced to each specific downstream resource before the call is made.&lt;/li&gt;
&lt;li&gt;⚙️ The agent runtime does use &lt;strong&gt;&lt;a href="https://learn.microsoft.com/entra/msal/python/" rel="noopener noreferrer"&gt;MSAL Python&lt;/a&gt;&lt;/strong&gt; to perform the exchange. That is not a proprietary bridge between the clouds; it is Microsoft's standards-based authentication library, the same one you would reach for to speak OAuth and OIDC to Entra from any Python application. The wire protocol is still OAuth and OIDC. MSAL is simply the most direct way to speak it from the agent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you already federate your AWS workloads to Microsoft Entra ID for human sign-in, this is the next step: it is time for your AI agents to get their identity from there too.&lt;/p&gt;

&lt;h2&gt;
  
  
  The token exchange, kept in its lane
&lt;/h2&gt;

&lt;p&gt;There is real machinery behind "acts on behalf of the user," and it is worth one honest paragraph rather than a victory lap of acronyms. Before each downstream call, the agent converts the inbound user token into a token scoped to the specific target resource, in-process, using &lt;a href="https://learn.microsoft.com/entra/msal/python/" rel="noopener noreferrer"&gt;MSAL Python&lt;/a&gt;. The result is a token whose audience is the AWS Lambda for the Lambda call, and the MCP server for the MCP call, with the original user identity preserved throughout. The two-stage exchange that Entra Agent ID uses to do this is &lt;a href="https://learn.microsoft.com/entra/agent-id/autonomous-agent-authentication-authorization-flow" rel="noopener noreferrer"&gt;documented here&lt;/a&gt;; it is the plumbing, not the headline. The headline is that the user's delegated context survives the entire trip, across clouds, to the downstream resources. And this chain can be infinite hops long.&lt;/p&gt;

&lt;h2&gt;
  
  
  The security posture, briefly
&lt;/h2&gt;

&lt;p&gt;A few properties matter more than the rest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔐 The agent never hands a credential to the model. Tools return only their response payloads; the inbound token lives in a tightly scoped variable that is cleared in a &lt;code&gt;finally&lt;/code&gt; block after every invocation and never reaches the LLM.&lt;/li&gt;
&lt;li&gt;🔍 Tokens are never logged. Only non-secret routing claims (issuer, audience, app id, scope, and the user's object id as a cache key) are emitted, never a token, header, or signature.&lt;/li&gt;
&lt;li&gt;The blueprint credential is read once per process and dropped from memory immediately after the client is constructed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the honest production caveat, because a PoC that hides its rough edges is selling something: this sample authenticates the agent's blueprint with a client secret, which is fine for a demo and &lt;a href="https://learn.microsoft.com/entra/agent-id/best-practices-agent-id" rel="noopener noreferrer"&gt;explicitly not recommended for production&lt;/a&gt;. The production path is a certificate or, better, a &lt;a href="https://learn.microsoft.com/entra/agent-id/create-blueprint#configure-credentials-for-the-agent-identity-blueprint" rel="noopener noreferrer"&gt;managed identity used as a federated credential&lt;/a&gt; so there is no stored secret at all. I have made &lt;a href="https://dev.to/astaykov/your-agentic-platform-doesnt-need-a-single-secret-managed-identities-workload-identity-3602"&gt;the broader case for a secret-less agentic platform before&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next, and the thesis
&lt;/h2&gt;

&lt;p&gt;The current PoC still keeps one secret on the AWS side: the blueprint credential. The next step closes that gap in the most fitting way possible: register AWS's own STS as a federated identity credential the Entra blueprint trusts, and let AWS issue the token that proves the agent's identity to Microsoft. At that point the loop is closed in both directions. AWS resources trust Microsoft-issued tokens, and Microsoft trusts AWS-issued tokens, with no shared secret anywhere between them.&lt;/p&gt;

&lt;p&gt;That is the whole thesis, and it is smaller than it sounds: a resource trusts a token, not a cloud. The delegation semantics that have governed &lt;a href="https://dev.to/astaykov/from-obo-apis-to-agent-identities-entra-conditional-access-still-works-the-same-140c"&gt;middle-tier APIs for years&lt;/a&gt; did not change when the middle tier became an AI agent, and they do not change when that agent moves to AWS. An identity is a protocol boundary. If your Lambda can trust Microsoft Entra Agent ID, your agent can run anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/astaykov/agentid-agentcore" rel="noopener noreferrer"&gt;astaykov/agentid-agentcore (the PoC)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/what-is-microsoft-entra-agent-id" rel="noopener noreferrer"&gt;What is Microsoft Entra Agent ID?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/autonomous-agent-authentication-authorization-flow" rel="noopener noreferrer"&gt;Authenticate and acquire tokens for autonomous agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/best-practices-agent-id" rel="noopener noreferrer"&gt;Best practices for Microsoft Entra Agent ID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/agent-id/create-blueprint" rel="noopener noreferrer"&gt;Create an agent identity blueprint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow" rel="noopener noreferrer"&gt;Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/msal/python/" rel="noopener noreferrer"&gt;MSAL for Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/entra/identity-platform/msal-overview" rel="noopener noreferrer"&gt;MSAL overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/graph/mcp-server/get-started" rel="noopener noreferrer"&gt;Get started with the Microsoft MCP Server for Enterprise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agents-tools-runtime.html" rel="noopener noreferrer"&gt;AWS Bedrock AgentCore Runtime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/identity.html" rel="noopener noreferrer"&gt;AWS Bedrock AgentCore Identity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html" rel="noopener noreferrer"&gt;Control access to HTTP APIs with JWT authorizers (API Gateway)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop.html" rel="noopener noreferrer"&gt;Develop HTTP APIs in API Gateway&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>entraagentid</category>
      <category>aws</category>
      <category>bedrockagentcore</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>A transformational AI agent does not start with the permissions it needs</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Wed, 17 Jun 2026 09:13:00 +0000</pubDate>
      <link>https://dev.to/astaykov/a-transformational-ai-agent-does-not-start-with-the-permissions-it-needs-4g8l</link>
      <guid>https://dev.to/astaykov/a-transformational-ai-agent-does-not-start-with-the-permissions-it-needs-4g8l</guid>
      <description>&lt;p&gt;Most teams are still building AI agents the way they built automation in 2019: create an identity, shovel a pile of permissions onto it, pray the list is not too dangerous, and call that least privilege. That model was weak for static applications. For AI agents, it is worse.&lt;/p&gt;

&lt;p&gt;An agent is not a static script. Its value comes from encountering new situations, discovering new APIs, and taking on work that was not fully known at deployment time. Pre-authorizing that kind of system is like issuing a master key because you do not know which doors the employee will need next month. Convenient, yes. Serious architecture, no.&lt;/p&gt;

&lt;p&gt;The more useful pattern is the opposite: start the agent with effectively zero useful permissions for the task in front of it, let it discover what permission is actually missing when it hits a boundary, and force any expansion of access through a governed path such as &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-access-packages" rel="noopener noreferrer"&gt;access packages for agent identities&lt;/a&gt;. That is the pattern I wanted to understand better, so I built a practical sample around it.&lt;/p&gt;

&lt;p&gt;The sample is &lt;a href="https://github.com/astaykov/n8n-aca" rel="noopener noreferrer"&gt;astaykov/n8n-aca&lt;/a&gt;, a one-command starter for &lt;a href="https://github.com/astaykov/n8n-aca" rel="noopener noreferrer"&gt;n8n on Azure Container Apps with Entra Agent ID&lt;/a&gt;. From Azure Cloud Shell, &lt;code&gt;azd up&lt;/code&gt; provisions the Azure infrastructure, creates the Entra objects, installs the custom Entra Agent ID node for n8n, wires the credentials, imports the workflows, and activates the triggers. It is the fastest way I know to get from "I want to test agentic identity patterns" to a running system without spending the afternoon on scaffolding.&lt;/p&gt;

&lt;p&gt;That convenience is not the interesting part, though. The interesting part is what the sample made easy to test: an autonomous agent on &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID&lt;/a&gt; that authenticates with its own identity, uses &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/authorization-agent-id#microsoft-graph-application-permissions" rel="noopener noreferrer"&gt;application permissions&lt;/a&gt; when it needs Microsoft Graph, and expands its access only through &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/agent-id-governance-overview" rel="noopener noreferrer"&gt;ID Governance&lt;/a&gt; when a real task justifies it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sample is the on-ramp, not the point
&lt;/h2&gt;

&lt;p&gt;The repo gives a practical "one-click" starting point, even if the literal mechanism is a single command rather than a portal button. It deploys n8n on Azure Container Apps, provisions the surrounding Azure services, and creates the Entra building blocks you need: an &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;agent identity blueprint and agent identity&lt;/a&gt;, plus the n8n credentials and workflows that let you immediately test autonomous and assistive patterns.&lt;/p&gt;

&lt;p&gt;That matters because identity architects do not need another abstract reference architecture. They need something they can stand up, inspect, and break. The sample gives you that. But the design pattern it enables is the real story.&lt;/p&gt;

&lt;p&gt;Microsoft Entra Agent ID exists precisely because traditional, deterministic application identities are the wrong abstraction for agents that evolve in production. Microsoft says that plainly: classic application identities were designed for static workloads and do not bring the governance model agents need, while &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;agent identities and blueprints&lt;/a&gt; add lifecycle, sponsorship, and policy structure that maps to how agents actually operate. Once you accept that framing, the next question becomes obvious: if the identity model is dynamic, why are we still designing permissions as if they were static?&lt;/p&gt;

&lt;h2&gt;
  
  
  The right starting state is deliberate under-permissioning
&lt;/h2&gt;

&lt;p&gt;When people hear "start with zero permissions," they often imagine an unusable toy. That is not what I mean.&lt;/p&gt;

&lt;p&gt;I mean zero useful permissions for the specific task the agent has not encountered yet.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/authorization-agent-id" rel="noopener noreferrer"&gt;authorization model for Entra Agent ID&lt;/a&gt; already points in that direction. Agents can use delegated permissions or application permissions, but high-risk permissions are blocked, lower-privilege access is preferred, and administrators are expected to grant access in a scoped way. &lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/agent-id-governance-overview" rel="noopener noreferrer"&gt;Governance for agent identities&lt;/a&gt; goes one step further by describing access packages as the structure through which agents can receive OAuth application permissions, group memberships, and Entra roles in a time-bound, auditable way.&lt;/p&gt;

&lt;p&gt;That combination changes the design target. The goal is no longer "figure out every permission the agent might need before go-live." The goal is "build an agent that can recognize a missing permission, identify the governed package that provides it, and request it through policy."&lt;/p&gt;

&lt;p&gt;That is the shift. It is subtle, but it is the whole game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the pattern actually lives in n8n
&lt;/h2&gt;

&lt;p&gt;At a glance, the workflow looks almost too simple to carry this much identity behavior: webhook in, token acquisition, AI agent, webhook out. That is exactly why the image earns its place here. The interesting part is not the number of nodes. It is the control logic concentrated inside the agent and its tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdzmccc6o7dmyf2yltxe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdzmccc6o7dmyf2yltxe.png" alt="The n8n workflow is visually simple by design: webhook, Entra token acquisition, AI agent, and response, with Azure OpenAI, memory, Microsoft Learn MCP, and Microsoft Graph attached as the agent's runtime dependencies." width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The workflow is intentionally compact. The design pattern does not live in a sprawling orchestration graph; it lives in the policy encoded into the AI Agent node and the constraints encoded into the Microsoft Graph tool.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/_9lcMliF0DU"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In my workflow, the pattern is not hidden in a policy engine or spread across ten helper scripts. It lives in two very concrete places:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The system prompt for the AI Agent node.&lt;/li&gt;
&lt;li&gt;The custom configuration of the HTTP Request tool that calls Microsoft Graph.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is worth emphasizing because too many "agentic architecture" discussions still pretend the prompt is fluff. It is not. In a tool-using agent, the system prompt is operational policy.&lt;/p&gt;

&lt;p&gt;The n8n &lt;a href="https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/" rel="noopener noreferrer"&gt;AI Agent node&lt;/a&gt; is a tools-based agent. It receives the user request, chooses tools, reasons about tool responses, and keeps going until it can answer or it hits a policy boundary. In this workflow, the agent is told something very specific:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an AI Agent with your own Microsoft Entra identity.
You authenticate as yourself using Microsoft Graph application permissions.
When any API call returns 401 or 403, do NOT give up.
Identify the exact permission, search access packages, inspect each package,
and request the matching package if self-request is allowed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That instruction is doing real architectural work. It teaches the agent to treat &lt;code&gt;401&lt;/code&gt; and &lt;code&gt;403&lt;/code&gt; as a discovery loop, not as a dead end.&lt;/p&gt;

&lt;p&gt;It also teaches the agent to stay honest about what kind of access it has. The prompt explicitly says it only works with application permissions for Microsoft Graph. That matters because &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts#agent-operation-patterns" rel="noopener noreferrer"&gt;Entra Agent ID distinguishes autonomous agents from assistive agents&lt;/a&gt;, and the permission model is different depending on whether the agent is acting as itself or on behalf of a user. For this workflow, the autonomous case is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Microsoft Learn MCP server is the underrated component
&lt;/h2&gt;

&lt;p&gt;The agent has two tools in the workflow: a Microsoft Graph HTTP tool and a Microsoft Learn MCP client pointing at &lt;code&gt;https://learn.microsoft.com/api/mcp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That second tool is the underrated component.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://learn.microsoft.com/en-us/training/support/mcp" rel="noopener noreferrer"&gt;Microsoft Learn MCP Server&lt;/a&gt; is public, free, and does not require authentication. More importantly, it gives the agent runtime access to official documentation and code examples through MCP instead of forcing you to hardcode every Microsoft Graph rule into the prompt. That is what turns the workflow from "an agent with a bag of fixed API calls" into "an agent that can learn how to call Graph correctly when it needs to."&lt;/p&gt;

&lt;p&gt;In practice, that means the agent can look up an endpoint, confirm which permission is required, and use the error it just received to tighten the search. That is the missing bridge between language-model flexibility and enterprise identity controls. Without it, the agent is guessing. With it, the agent has a documentation brain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The HTTP tool matters just as much as the prompt
&lt;/h2&gt;

&lt;p&gt;The n8n &lt;a href="https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/" rel="noopener noreferrer"&gt;HTTP Request node&lt;/a&gt; is versatile enough to be dangerous, which is exactly why the custom tool configuration matters.&lt;/p&gt;

&lt;p&gt;In this workflow, the HTTP tool is constrained to &lt;code&gt;https://graph.microsoft.com&lt;/code&gt;, prefers &lt;code&gt;/v1.0/&lt;/code&gt; over &lt;code&gt;/beta/&lt;/code&gt;, uses a predefined bearer credential, and is instructed to research the endpoint before writes. More importantly, it is configured to return the &lt;strong&gt;full response&lt;/strong&gt; and &lt;strong&gt;never error&lt;/strong&gt;. That is not a cosmetic choice. It means the agent gets the status code and body back even when Graph refuses the call, so it can reason over the authorization failure instead of having the workflow short-circuit.&lt;/p&gt;

&lt;p&gt;That one setting turns a generic REST tool into a permission-discovery instrument.&lt;/p&gt;

&lt;p&gt;The tool instructions also tell the agent to confirm state-changing operations before execution, except for one case: creating an &lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-post-assignmentrequests?view=graph-rest-1.0" rel="noopener noreferrer"&gt;access package assignment request&lt;/a&gt;. That exception is deliberate. If the whole point is to let the agent acquire governed access in context, then the request path itself needs to be part of the autonomous loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the governed escalation loop works
&lt;/h2&gt;

&lt;p&gt;The loop is simple enough to explain, which is usually a sign you are finally dealing with the right abstraction.&lt;/p&gt;

&lt;p&gt;First, the agent attempts the Graph operation the user asked for.&lt;/p&gt;

&lt;p&gt;If Microsoft Graph returns &lt;code&gt;401&lt;/code&gt; or &lt;code&gt;403&lt;/code&gt;, the agent uses the error plus the Learn MCP server to identify the exact missing permission. The prompt forces it to write down the permission explicitly and to treat it as an application permission in this workflow.&lt;/p&gt;

&lt;p&gt;Next, it enumerates the available access packages with &lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-list-accesspackages?view=graph-rest-1.0" rel="noopener noreferrer"&gt;GET &lt;code&gt;/identityGovernance/entitlementManagement/accessPackages&lt;/code&gt;&lt;/a&gt;. Then it inspects the package contents through &lt;a href="https://learn.microsoft.com/en-us/graph/api/accesspackage-list-resourcerolescopes?view=graph-rest-1.0" rel="noopener noreferrer"&gt;resource role scopes&lt;/a&gt;, looking for the role that maps to the missing permission. This is the key architectural move: the agent is not inventing new access. It is discovering which pre-governed package the identity team already made available.&lt;/p&gt;

&lt;p&gt;Once it finds the matching package, it reads the &lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-list-assignmentpolicies?view=graph-rest-1.0" rel="noopener noreferrer"&gt;assignment policies&lt;/a&gt; to determine whether self-request is allowed. If it is, the agent creates a &lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-post-assignmentrequests?view=graph-rest-1.0" rel="noopener noreferrer"&gt;POST &lt;code&gt;/identityGovernance/entitlementManagement/assignmentRequests&lt;/code&gt;&lt;/a&gt; call for itself. If self-request is not allowed, it gives the user the package name, what it grants, and the My Access link so the user, their manager, or the sponsor can request it on the agent's behalf.&lt;/p&gt;

&lt;p&gt;That is the pattern in one sentence: the agent can discover and request governed access, but it cannot bypass governance.&lt;/p&gt;

&lt;p&gt;This is why &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-access-packages" rel="noopener noreferrer"&gt;access packages for agent identities&lt;/a&gt; matter so much. Microsoft explicitly supports three pathways: the agent can request access programmatically, the sponsor can request it on behalf of the agent, or an administrator can assign it directly. The workflow leans into those pathways instead of trying to outsmart them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why identity architects should care
&lt;/h2&gt;

&lt;p&gt;This is not just a clever n8n trick. It is a better control model.&lt;/p&gt;

&lt;p&gt;When an identity team pre-grants broad application permissions to an agent, they are making an up-front guess about future behavior. Those guesses age badly. They are rarely revisited, almost never shrunk, and eventually become the authorization equivalent of legacy firewall rules.&lt;/p&gt;

&lt;p&gt;Access packages change the conversation. They let the identity team define bundles of allowed access, the &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-access-packages" rel="noopener noreferrer"&gt;approval and request policies&lt;/a&gt;, the expiration model, and the human accountability path. The agent still moves fast, but the boundary conditions are owned by governance, not improvised in code.&lt;/p&gt;

&lt;p&gt;That is why I think this pattern matters: it decouples &lt;strong&gt;permission discovery&lt;/strong&gt; from &lt;strong&gt;permission approval&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The agent is free to discover what it needs. The organization is still in control of whether that need maps to an approved package, whether self-request is allowed, who must approve it, and when the access expires. That is a much more adult architecture than stuffing &lt;code&gt;Directory.Read.All&lt;/code&gt; into an app registration because the pilot customer wants the demo today.&lt;/p&gt;

&lt;h2&gt;
  
  
  The uncomfortable but necessary conclusion
&lt;/h2&gt;

&lt;p&gt;The industry still talks about agent permissions as if the main design question were "what should this agent have?" That is already the wrong question.&lt;/p&gt;

&lt;p&gt;The better question is: &lt;em&gt;how should this agent acquire access when reality teaches us that the original permission set was incomplete?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If your answer is "we will update the app registration manually," you do not have an agentic permission model. You have an operations backlog.&lt;/p&gt;

&lt;p&gt;If your answer is "the agent starts narrow, learns what permission is missing from the task and the docs, maps that need to a governed access package, and either requests it or hands the human the approval path," then you are finally designing for the world these systems actually live in.&lt;/p&gt;

&lt;p&gt;That is what this sample helped me understand. n8n on Azure Container Apps with Entra Agent ID is a useful accelerator. The deeper lesson is the design pattern itself: agents should not begin life over-permissioned. They should begin life constrained, then &lt;em&gt;earn&lt;/em&gt; their scope through policy, context, and governance.&lt;/p&gt;

&lt;p&gt;That shift is the part identity architects should care about.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/astaykov/n8n-aca" rel="noopener noreferrer"&gt;astaykov/n8n-aca&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID key concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/authorization-agent-id" rel="noopener noreferrer"&gt;Authorization in Microsoft Entra Agent ID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-access-packages" rel="noopener noreferrer"&gt;Access packages for agent identities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/id-governance/agent-id-governance-overview" rel="noopener noreferrer"&gt;Governing agent identities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-post-assignmentrequests?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Create accessPackageAssignmentRequest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-list-accesspackages?view=graph-rest-1.0" rel="noopener noreferrer"&gt;List accessPackages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/accesspackage-list-resourcerolescopes?view=graph-rest-1.0" rel="noopener noreferrer"&gt;List resourceRoleScopes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/entitlementmanagement-list-assignmentpolicies?view=graph-rest-1.0" rel="noopener noreferrer"&gt;List assignmentPolicies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/training/support/mcp" rel="noopener noreferrer"&gt;Microsoft Learn MCP Server overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/" rel="noopener noreferrer"&gt;n8n AI Agent node&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/" rel="noopener noreferrer"&gt;n8n HTTP Request node&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>entraagentid</category>
      <category>n8n</category>
      <category>identitygovernance</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>Seeing every agent sign-in in one place: an Azure Monitor workbook for Entra Agent ID</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Wed, 10 Jun 2026 10:23:00 +0000</pubDate>
      <link>https://dev.to/astaykov/seeing-every-agent-sign-in-in-one-place-an-azure-monitor-workbook-for-entra-agent-id-4dgp</link>
      <guid>https://dev.to/astaykov/seeing-every-agent-sign-in-in-one-place-an-azure-monitor-workbook-for-entra-agent-id-4dgp</guid>
      <description>&lt;p&gt;The earlier articles in this series (&lt;a href="https://dev.to/astaykov/the-overlooked-gem-in-microsoft-entra-that-gives-your-ai-agents-super-powers-3mde"&gt;Part 1&lt;/a&gt;, &lt;a href="https://dev.to/astaykov/your-agent-is-becoming-the-crown-jewel-soc-reviews-and-governance-for-the-dynamic-consent-era-23l3"&gt;Part 2&lt;/a&gt;, and &lt;a href="https://dev.to/astaykov/finding-out-what-your-ai-agents-actually-got-discovering-consents-and-active-agents-in-microsoft-1eeo"&gt;Part 3&lt;/a&gt;) built the case from first principles: dynamic consent lets an agent earn its access in context, that accumulation quietly turns the agent into a high-value target, and the raw queries to discover what agents have been granted and what they actually exercise already exist in Microsoft Graph and Log Analytics. All of that is useful. None of it is visible unless someone remembers to run the query.&lt;/p&gt;

&lt;p&gt;A KQL query in a Log Analytics window is something you execute when you already suspect a problem. An &lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/workbooks-overview" rel="noopener noreferrer"&gt;Azure Monitor workbook&lt;/a&gt; is a parameterized view you open (or pin to a shared dashboard) to see the shape of agent traffic &lt;em&gt;before&lt;/em&gt; suspicion sets in. That is a different posture entirely, and it is the difference between investigation and awareness.&lt;/p&gt;

&lt;p&gt;This article walks through an open-source workbook that provides that awareness for every agent identity in the tenant, grouped by the construct that matters most for governance: the Agent Identity Blueprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the workbook shows
&lt;/h2&gt;

&lt;p&gt;The workbook, &lt;a href="https://github.com/Dayzure/entra-agent-id-workbooks" rel="noopener noreferrer"&gt;available on GitHub&lt;/a&gt;, queries two log tables from Microsoft Entra:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;AADNonInteractiveUserSignInLogs&lt;/code&gt;&lt;/strong&gt; for delegated agent sign-ins, where an agent identity acts on behalf of a human user (or on behalf of another agent user).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;AADServicePrincipalSignInLogs&lt;/code&gt;&lt;/strong&gt; for autonomous agent sign-ins, where the agent identity authenticates with its own application-level credentials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both views are grouped by &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Agent Identity Blueprint&lt;/a&gt;, which is the parent construct that defines the agent's trust boundary. This is deliberate. &lt;a href="https://dev.to/astaykov/your-agent-is-becoming-the-crown-jewel-soc-reviews-and-governance-for-the-dynamic-consent-era-23l3"&gt;Part 2&lt;/a&gt; argued that the blueprint is the right choke point for Conditional Access and governance policy, because a policy applied to a blueprint propagates to every agent identity created from it. The workbook follows the same principle: start at the blueprint, drill into the agents underneath, then into the individual sign-in events.&lt;/p&gt;

&lt;p&gt;The top-level summary tiles show total sign-in counts, unique agent identities, successes, failures, and interrupts (pending user action), each with a sparkline trend. Clicking a tile filters the rest of the workbook to that status category.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites and deployment
&lt;/h2&gt;

&lt;p&gt;The workbook requires a &lt;a href="https://learn.microsoft.com/en-us/entra/identity/monitoring-health/howto-integrate-activity-logs-with-azure-monitor-logs" rel="noopener noreferrer"&gt;Log Analytics workspace with Microsoft Entra sign-in logs flowing&lt;/a&gt; into it. Specifically, the &lt;strong&gt;non-interactive user sign-in logs&lt;/strong&gt; and &lt;strong&gt;service principal sign-in logs&lt;/strong&gt; diagnostic categories must be enabled in the Entra diagnostic settings. If you already have Entra sign-in logs routed to Log Analytics (most organizations with any monitoring posture do), you are ready.&lt;/p&gt;

&lt;p&gt;To deploy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download &lt;a href="https://github.com/Dayzure/entra-agent-id-workbooks/blob/main/agent-id-sign-ins.json" rel="noopener noreferrer"&gt;&lt;code&gt;agent-id-sign-ins.json&lt;/code&gt;&lt;/a&gt; from the GitHub repo.&lt;/li&gt;
&lt;li&gt;In the Azure portal, navigate to &lt;strong&gt;Azure Monitor &amp;gt; Workbooks &amp;gt; New&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Advanced Editor&lt;/strong&gt; (the &lt;code&gt;&amp;lt;/&amp;gt;&lt;/code&gt; icon in the toolbar).&lt;/li&gt;
&lt;li&gt;Paste the JSON content and click &lt;strong&gt;Apply&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select your Log Analytics workspace and save.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is it. The parameters at the top of the workbook (time range, agent identity filter, user filter) populate automatically from the data in your workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delegated agent sign-ins
&lt;/h2&gt;

&lt;p&gt;The upper section of the workbook covers sign-ins where an agent identity acts in a delegated context, on behalf of a user. This is the pattern that &lt;a href="https://dev.to/astaykov/the-overlooked-gem-in-microsoft-entra-that-gives-your-ai-agents-super-powers-3mde"&gt;Part 1&lt;/a&gt; described: the agent acquires tokens with the user's consent, and each sign-in event is recorded in &lt;code&gt;AADNonInteractiveUserSignInLogs&lt;/code&gt; with the &lt;code&gt;Agent&lt;/code&gt; property that identifies the agent type and its parent blueprint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnsm1v3zidsnnv4v3uvzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnsm1v3zidsnnv4v3uvzu.png" alt="Workbook view showing delegated sign-ins grouped by Agent Blueprint, with the Entra SDK Blueprint expanded to show two human users and one agent user, plus sign-in details with resources and OAuth scopes" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The hierarchy works like this: blueprints sit at the top level, each showing total sign-in count, a trend sparkline, failure count, and interrupt count. Expanding a blueprint reveals the agent identities created from it. Selecting a row on the left populates the detail grid on the right.&lt;/p&gt;

&lt;p&gt;The detail grid is where the operational value lives. Each sign-in event shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;type indicator&lt;/strong&gt;: 🙋 for a human user or 🤖 for an agent user (identified by &lt;code&gt;agentSubjectType == 'agentIDuser'&lt;/code&gt; in the sign-in log).&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;display name&lt;/strong&gt; of the user or agent user who was the subject of the sign-in.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;resource&lt;/strong&gt; that was accessed (Microsoft Graph, Azure DevOps, a custom API).&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;OAuth scopes&lt;/strong&gt; that were included in the token, extracted from the &lt;code&gt;AuthenticationProcessingDetails&lt;/code&gt; field of the sign-in event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign-in status&lt;/strong&gt;, &lt;strong&gt;Conditional Access status&lt;/strong&gt;, and error details when something went wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent identity names in the left panel are clickable links that open the &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Agent Identity blade&lt;/a&gt; directly in the Microsoft Entra admin center. No copying of object IDs, no navigating through menus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabm5le7spsga344sbjvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabm5le7spsga344sbjvu.png" alt="Workbook view with two blueprints expanded, showing the Az DevOops Blueprint with a selected agent identity whose sign-ins show Azure DevOps access with user_impersonation scope" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice what this view makes immediately obvious. In the screenshot above, the "Az DevOops Blueprint" has agent identities signing into Azure DevOps with &lt;code&gt;user_impersonation&lt;/code&gt; scope. That is the exact scenario from &lt;a href="https://dev.to/astaykov/your-ai-agent-doesnt-need-a-pat-to-work-in-azure-devops-fl8"&gt;the Azure DevOps article&lt;/a&gt;: an agent identity replacing a PAT with proper delegated access. The workbook shows it happening in production, with the user on whose behalf the agent acted, the resource it touched, and the scopes it used. If an unexpected resource or scope appears in that list, it is visible here without running a query.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autonomous agent sign-ins
&lt;/h2&gt;

&lt;p&gt;The lower section covers the other half: agents authenticating with application-level credentials, without a user context. These are the autonomous agents, the ones that run scheduled jobs, background processing, or act as service accounts with &lt;code&gt;appRoleAssignments&lt;/code&gt; rather than delegated consent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7aqmz2qi6amycxoiqrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7aqmz2qi6amycxoiqrr.png" alt="Workbook view showing autonomous agent sign-ins grouped by blueprint, with agent identities accessing Claude Service Account, Anthropic WIF Trust, Anthropic APIs, and Microsoft Graph" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This section queries &lt;code&gt;AADServicePrincipalSignInLogs&lt;/code&gt; filtered to &lt;code&gt;agentType == 'agenticAppInstance'&lt;/code&gt;, and uses the same blueprint-first hierarchy. Expanding a blueprint shows each agent identity, and now each agent identity row also shows the &lt;strong&gt;Resources&lt;/strong&gt; column: a comma-separated list of every resource that agent has signed into during the selected time range. That is the agent's behavioral surface area in one cell.&lt;/p&gt;

&lt;p&gt;The screenshot tells a real story. The Anthropic agent identity, created from its blueprint, has signed into Claude Service Account, Anthropic WIF Trust, Anthropic APIs, and Microsoft Graph. That is the &lt;a href="https://dev.to/astaykov/your-agentic-platform-doesnt-need-a-single-secret-managed-identities-workload-identity-3602"&gt;secretless authentication pattern&lt;/a&gt; in action: the agent uses Workload Identity Federation to authenticate to Anthropic's APIs without an API key, and the sign-in logs capture every hop. The four failures against "Unknown Resource" are worth investigating (resource identity not resolved at sign-in time, typically a transient issue or a misconfigured resource), and they are visible here instead of hiding in a raw log table.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the workbook does not show
&lt;/h2&gt;

&lt;p&gt;This workbook covers the &lt;em&gt;behavioral&lt;/em&gt; side of agent visibility: who signed in, to what resource, with which scopes, and whether it worked. It does not show what was &lt;em&gt;granted&lt;/em&gt; via &lt;code&gt;oauth2PermissionGrants&lt;/code&gt; or &lt;code&gt;appRoleAssignments&lt;/code&gt;. That is the &lt;em&gt;entitlement&lt;/em&gt; side, and it lives in the Microsoft Graph queries covered in &lt;a href="https://dev.to/astaykov/finding-out-what-your-ai-agents-actually-got-discovering-consents-and-active-agents-in-microsoft-1eeo"&gt;Part 3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The two are complementary. The workbook answers "what are agents doing?" The Graph queries answer "what could agents do?" The gap between the two, the granted-but-never-exercised permissions, is what &lt;a href="https://dev.to/astaykov/your-agent-is-becoming-the-crown-jewel-soc-reviews-and-governance-for-the-dynamic-consent-era-23l3"&gt;Part 2&lt;/a&gt; called the access-review backlog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;The workbook is open source and available at &lt;a href="https://github.com/Dayzure/entra-agent-id-workbooks" rel="noopener noreferrer"&gt;github.com/Dayzure/entra-agent-id-workbooks&lt;/a&gt;. Import it, point it at your Log Analytics workspace, and see what your agents have been doing. If the answer surprises you, the earlier articles in this series explain what to do about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Dayzure/entra-agent-id-workbooks" rel="noopener noreferrer"&gt;Entra Agent ID workbook (GitHub)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/workbooks-overview" rel="noopener noreferrer"&gt;Azure Monitor workbooks overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/monitoring-health/concept-sign-ins" rel="noopener noreferrer"&gt;Microsoft Entra sign-in logs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/monitoring-health/howto-integrate-activity-logs-with-azure-monitor-logs" rel="noopener noreferrer"&gt;Integrate Entra activity logs with Azure Monitor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID key concepts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>entra</category>
      <category>entraagentid</category>
      <category>aiagents</category>
      <category>azuremonitor</category>
    </item>
    <item>
      <title>Your AI agent doesn't need a PAT to work in Azure DevOps</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Thu, 04 Jun 2026 09:17:00 +0000</pubDate>
      <link>https://dev.to/astaykov/your-ai-agent-doesnt-need-a-pat-to-work-in-azure-devops-fl8</link>
      <guid>https://dev.to/astaykov/your-ai-agent-doesnt-need-a-pat-to-work-in-azure-devops-fl8</guid>
      <description>&lt;p&gt;At &lt;a href="https://collabsummit.eu/" rel="noopener noreferrer"&gt;Collab Summit 2026&lt;/a&gt; in the beginning of May, a fellow I had not seen in years caught me between sessions. We did the usual catching up, and then he got to the real question: "We're building an AI agent that works inside Azure DevOps. It creates work items, pushes code to branches, opens pull requests. Right now it authenticates with a PAT. How do we do this &lt;em&gt;properly&lt;/em&gt;?"&lt;/p&gt;

&lt;p&gt;The room around us was full of people building similar things. AI agents that are not chatbots answering questions, but &lt;em&gt;digital co-workers&lt;/em&gt;: autonomous participants on a development team, shipping code, triaging issues, responding to reviewer feedback. The pattern is already in production across more organizations than most conference talks acknowledge.&lt;/p&gt;

&lt;p&gt;His question deserved a better answer than "use a service principal." So I went home and built one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The identity primitives that were never designed for this
&lt;/h2&gt;

&lt;p&gt;When a non-human caller needs to authenticate &lt;em&gt;to&lt;/em&gt; Azure DevOps, two standard options exist today. Neither was designed for an autonomous AI agent acting as a member of a development team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Personal Access Tokens (PATs).&lt;/strong&gt; A &lt;a href="https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate" rel="noopener noreferrer"&gt;PAT&lt;/a&gt; is a static bearer credential tied to a human user. It carries that user's identity and permissions, which means the agent's actions appear in audit logs as if the human performed them. There is no way to distinguish "the developer pushed a commit" from "the developer's agent pushed a commit." The token does not expire unless someone sets a date and remembers it. It cannot be scoped to a governed agent identity. It is a secret that sits in an environment variable and waits to be leaked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Entra workload identities (service principals and managed identities).&lt;/strong&gt; Azure DevOps now supports &lt;a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/library/add-devops-entra-service-connection?view=azure-devops" rel="noopener noreferrer"&gt;Entra workload identity authentication&lt;/a&gt; for pipelines, which is a genuine improvement: service principals and managed identities can be added as users to an Azure DevOps organization, and pipelines authenticate to Azure DevOps resources through Workload Identity Federation with zero stored secrets. The credentials problem is solved. But the identity &lt;em&gt;model&lt;/em&gt; is still the pipeline model. A service principal added to an ADO organization has no concept of owner, sponsor, or blueprint. It has no delegated user pattern. Your SOC cannot filter its sign-in events as agentic activity. It is infrastructure plumbing designed for CI/CD jobs accessing repos and artifact feeds, not for a digital co-worker whose commits, work items, and PR comments should carry a traceable, governed agent identity with lifecycle metadata.&lt;/p&gt;

&lt;p&gt;Both options were designed for a world where non-human callers were pipelines, scheduled jobs, or integration hooks. That world is not the one we are building in anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an AI agent actually needs
&lt;/h2&gt;

&lt;p&gt;An AI agent that operates as a digital co-worker on a development team needs something fundamentally different from a pipeline credential. It needs an &lt;em&gt;identity&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Not a token. Not a secret. An identity with the same governance surface that a human team member carries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An owner&lt;/strong&gt; who is accountable for what the agent does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A sponsor&lt;/strong&gt; with business context for why the agent exists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditable sign-in events&lt;/strong&gt; that your SOC can filter, correlate, and alert on, tagged explicitly as agentic activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A credential model&lt;/strong&gt; where the agent's runtime code never touches secrets (because secrets in agent memory are an attack surface, not a convenience).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A lifecycle&lt;/strong&gt; that ties the identity to the agent's existence, so decommissioning the agent means decommissioning its access.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a wishlist for a future platform. This is what &lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/agent-id-overview" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID&lt;/a&gt; provides today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entra Agent ID: the IAM shift
&lt;/h2&gt;

&lt;p&gt;If you have followed this series, you have seen Entra Agent ID applied to &lt;a href="https://dev.to/astaykov/your-ai-agent-doesnt-need-an-api-key-entra-agent-id-and-anthropics-workload-identity-federation-el0"&gt;calling third-party model APIs without API keys&lt;/a&gt; and to &lt;a href="https://dev.to/astaykov/your-agentic-platform-doesnt-need-a-single-secret-managed-identities-workload-identity-3602"&gt;building secret-less agentic platforms with managed identities and Workload Identity Federation&lt;/a&gt;. The pattern is consistent, but it is worth stating the fundamental shift plainly, because it changes how we think about IAM for AI agents.&lt;/p&gt;

&lt;p&gt;Traditional IAM for non-human workloads treats the workload as infrastructure. You create a service principal, hand it credentials, scope its permissions, and monitor it (if you remember) through workload identity logs that most SOC teams never look at. The workload has no owner in the governance sense. It has no sponsor. It has no blueprint that propagates policy to every instance. It is a row in an app registration table that someone created two years ago and nobody is sure whether it is still in use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID&lt;/a&gt; treats the AI agent as a &lt;em&gt;participant&lt;/em&gt;. The identity constructs are purpose-built:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint" rel="noopener noreferrer"&gt;Agent Identity Blueprints&lt;/a&gt;&lt;/strong&gt; are the authentication foundation and the policy anchor. A blueprint holds (or federates) the credentials and parents one or more agent identities. Conditional Access policies applied to a blueprint propagate to every agent identity it creates. One policy decision, enforced across an entire family of agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-identities" rel="noopener noreferrer"&gt;Agent Identities&lt;/a&gt;&lt;/strong&gt; are the runtime identity of a specific agent. No credentials of their own. They authenticate through their blueprint. They carry owner and sponsor metadata. They produce sign-in events tagged as agentic, visible in the same logs your SOC already monitors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/endpoints" rel="noopener noreferrer"&gt;Entra SDK Auth Sidecar&lt;/a&gt;&lt;/strong&gt; handles all credential work in a separate container. The agent code never sees a secret, never handles token acquisition, never stores credentials in memory. The sidecar is &lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/security" rel="noopener noreferrer"&gt;not exposed to the host network&lt;/a&gt;, so the token acquisition surface is isolated from the agent's own attack surface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a better way to do service principals. It is a different category.&lt;/p&gt;

&lt;h2&gt;
  
  
  The delegated user pattern and Azure DevOps
&lt;/h2&gt;

&lt;p&gt;For an AI agent that acts as a digital co-worker on a development team, the &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/concept-agent-id-design-patterns" rel="noopener noreferrer"&gt;Agent ID User (delegated) pattern&lt;/a&gt; is the right fit. The agent acts on behalf of a specific user (its own agent user account in Entra), and every action it takes in Azure DevOps carries that user's identity.&lt;/p&gt;

&lt;p&gt;The identity flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The sidecar authenticates to Entra ID using the blueprint's credentials.&lt;/li&gt;
&lt;li&gt;The agent requests a token from the sidecar for Azure DevOps, specifying its Agent Identity and its Agent Username.&lt;/li&gt;
&lt;li&gt;The sidecar performs the Federated Identity Credential (FIC) token exchange with Entra ID.&lt;/li&gt;
&lt;li&gt;Entra issues a Bearer token scoped to the Azure DevOps resource (&lt;code&gt;499b84ac-1321-427f-aa17-267ca6975798&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The agent calls the &lt;a href="https://learn.microsoft.com/en-us/rest/api/azure/devops/" rel="noopener noreferrer"&gt;Azure DevOps REST API&lt;/a&gt; with that token.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The agent user is a real member of the Azure DevOps organization, with its own access level, project permissions, and repository access. When the agent creates a work item, it appears as created by the agent user. When it pushes a commit, the commit author is the agent user. When it opens a pull request, the PR creator is the agent user. The audit trail is clean, attributable, and governed.&lt;/p&gt;

&lt;p&gt;No PAT. No service connection. No secret stored in agent code. The only credential in the system is the blueprint's, managed by the sidecar in an isolated container.&lt;/p&gt;

&lt;h2&gt;
  
  
  The proof of concept
&lt;/h2&gt;

&lt;p&gt;I built a &lt;a href="https://github.com/astaykov/agentid-azure-devops" rel="noopener noreferrer"&gt;proof of concept&lt;/a&gt; that demonstrates the full pattern. The agent is powered by Azure OpenAI with &lt;a href="https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/function-calling" rel="noopener noreferrer"&gt;function calling&lt;/a&gt; and can create work items, push file changes to new branches, open pull requests with reviewer assignments, read PR comment threads, and reply to reviewer feedback.&lt;/p&gt;

&lt;p&gt;The architecture is deliberately simple: two containers on a Docker bridge network. The &lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/configuration" rel="noopener noreferrer"&gt;Entra SDK auth sidecar&lt;/a&gt; handles token acquisition; the agent handles DevOps operations. The sidecar has no host port exposure (per &lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/security" rel="noopener noreferrer"&gt;Microsoft's security guidance&lt;/a&gt;); the agent exposes a chat interface on port 4192 for demonstration purposes only.&lt;/p&gt;

&lt;p&gt;The chat interface is there because it makes it easy to observe what the agent is doing during a demo. In a production deployment, the agent would be fully autonomous: triggered by events (a new issue, a failing build, a PR review request), executing its DevOps workflow, and reporting results through whatever channel the team uses. The identity model is identical either way.&lt;/p&gt;

&lt;p&gt;The PoC includes a chat UI where you can give the agent instructions like "Create an issue titled 'Fix login timeout', push a fix to a new branch, and open a PR for it." The agent orchestrates the entire flow, calling Azure DevOps REST APIs through the sidecar-acquired tokens. The &lt;a href="https://github.com/astaykov/agentid-azure-devops#readme" rel="noopener noreferrer"&gt;repository README&lt;/a&gt; covers the prerequisites, the Entra configuration (including the &lt;a href="https://learn.microsoft.com/en-us/graph/api/oauth2permissiongrant-post?view=graph-rest-1.0" rel="noopener noreferrer"&gt;delegated permission grants&lt;/a&gt; that are easy to miss), and the Docker Compose setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Entra side requires
&lt;/h2&gt;

&lt;p&gt;The Entra configuration involves four objects, and the relationship between them is worth understanding even if the README walks you through it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A Blueprint app registration&lt;/strong&gt; that holds the credentials (client secret for local development; &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity" rel="noopener noreferrer"&gt;managed identity as a federated credential&lt;/a&gt; for production, as covered in a &lt;a href="https://dev.to/astaykov/your-agentic-platform-doesnt-need-a-single-secret-managed-identities-workload-identity-3602"&gt;previous article in this series&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An Agent Identity&lt;/strong&gt; (service principal) created from the blueprint. This is the agent's runtime identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An Agent User&lt;/strong&gt; in your Entra tenant. This is the user account the agent acts on behalf of.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegated permission grants&lt;/strong&gt; created via Microsoft Graph's &lt;a href="https://learn.microsoft.com/en-us/graph/api/oauth2permissiongrant-post?view=graph-rest-1.0" rel="noopener noreferrer"&gt;&lt;code&gt;oauth2PermissionGrant&lt;/code&gt;&lt;/a&gt; endpoint. The Agent Identity needs &lt;code&gt;user_impersonation&lt;/code&gt; on the Azure DevOps resource and the standard OpenID Connect scopes on Microsoft Graph. These grants must be scoped to the Agent User (consent type &lt;code&gt;Principal&lt;/code&gt;, not &lt;code&gt;AllPrincipals&lt;/code&gt;). This is the step most people miss on their first attempt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the Azure DevOps side requires
&lt;/h2&gt;

&lt;p&gt;The Azure DevOps side is surprisingly straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The organization must be backed by the same Entra tenant.&lt;/li&gt;
&lt;li&gt;The Agent User must be a member of the organization with &lt;strong&gt;Basic&lt;/strong&gt; access level (Stakeholders cannot access Code/Repos).&lt;/li&gt;
&lt;li&gt;The Agent User needs project-level permissions: Work Items (Read/Write), Code (Contribute), and Pull Requests (Create) on the target project and repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is it. No service connection to configure. No PAT to mint and rotate. The agent authenticates through Entra, and Azure DevOps sees a regular user with scoped permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  From demo to production
&lt;/h2&gt;

&lt;p&gt;The PoC runs on Docker Compose with a client secret for the blueprint. A production deployment changes three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Replace the client secret&lt;/strong&gt; with a &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity" rel="noopener noreferrer"&gt;managed identity federated credential&lt;/a&gt; or a &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;Workload Identity Federation&lt;/a&gt; credential from your compute platform (AKS, Container Apps, etc.). The sidecar supports both through its &lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/configuration" rel="noopener noreferrer"&gt;credential source configuration&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the sidecar for Azure OpenAI authentication too.&lt;/strong&gt; The PoC uses an API key for Azure OpenAI because the focus is on the Azure DevOps identity pattern, but in production, the sidecar should acquire tokens for the Cognitive Services resource as well. No reason to have &lt;em&gt;any&lt;/em&gt; static secret in the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add the governance layer.&lt;/strong&gt; Wire the agent's sign-in events into your SOC monitoring. Set up access reviews keyed to actual API usage, not calendar recertification. Apply Conditional Access policies to the blueprint. Earlier articles in this series (&lt;a href="https://dev.to/astaykov/your-agent-is-becoming-the-crown-jewel-soc-reviews-and-governance-for-the-dynamic-consent-era-23l3"&gt;governance&lt;/a&gt; and &lt;a href="https://dev.to/astaykov/finding-out-what-your-ai-agents-actually-got-discovering-consents-and-active-agents-in-microsoft-1eeo"&gt;discovering consents&lt;/a&gt;) cover the governance model in detail.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The answer to the question
&lt;/h2&gt;

&lt;p&gt;The fellow at Collab Summit asked how to connect an AI agent to Azure DevOps properly. The answer is not a better secret. It is a better identity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/agent-id-overview" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID&lt;/a&gt; gives the agent a governed, auditable, purpose-built identity. The &lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/endpoints" rel="noopener noreferrer"&gt;Entra SDK auth sidecar&lt;/a&gt; keeps credentials out of agent code. The delegated user pattern makes the agent a traceable participant in Azure DevOps, not an anonymous caller hiding behind a PAT.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/astaykov/agentid-azure-devops" rel="noopener noreferrer"&gt;proof of concept&lt;/a&gt; is on GitHub. Clone it, configure the Entra objects, run &lt;code&gt;docker compose up&lt;/code&gt;, and watch an AI agent create issues, push code, and open pull requests, all authenticated through its own agent identity.&lt;/p&gt;

&lt;p&gt;If your AI agents are still running on PATs, the question from Collab Summit applies to you too. And the answer is the same: stop managing secrets. Start managing identities.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/agent-id-overview" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint" rel="noopener noreferrer"&gt;Agent Identity Blueprints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-identities" rel="noopener noreferrer"&gt;Agent Identities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/key-concepts" rel="noopener noreferrer"&gt;Agent ID key concepts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/concept-agent-id-design-patterns" rel="noopener noreferrer"&gt;Agent ID design patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/endpoints" rel="noopener noreferrer"&gt;Entra SDK Auth Sidecar — Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/configuration" rel="noopener noreferrer"&gt;Entra SDK Auth Sidecar — Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/security" rel="noopener noreferrer"&gt;Entra SDK Auth Sidecar — Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/rest/api/azure/devops/" rel="noopener noreferrer"&gt;Azure DevOps REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate" rel="noopener noreferrer"&gt;Azure DevOps PATs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/library/add-devops-entra-service-connection?view=azure-devops" rel="noopener noreferrer"&gt;Access Azure DevOps with Microsoft Entra workload identity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/oauth2permissiongrant-post?view=graph-rest-1.0" rel="noopener noreferrer"&gt;oauth2PermissionGrant — Microsoft Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity" rel="noopener noreferrer"&gt;Configure an app to trust a managed identity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;Workload Identity Federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/function-calling" rel="noopener noreferrer"&gt;Azure OpenAI Function Calling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/astaykov/agentid-azure-devops" rel="noopener noreferrer"&gt;Proof of concept — agentid-azure-devops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://collabsummit.eu/" rel="noopener noreferrer"&gt;Collab Summit 2026&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>entraagentid</category>
      <category>azuredevops</category>
      <category>aiagents</category>
      <category>identity</category>
    </item>
    <item>
      <title>Your agentic platform doesn't need a single secret: Managed Identities, Workload Identity Federation and Agent Identity Blueprints</title>
      <dc:creator>Anton Staykov</dc:creator>
      <pubDate>Thu, 28 May 2026 10:17:00 +0000</pubDate>
      <link>https://dev.to/astaykov/your-agentic-platform-doesnt-need-a-single-secret-managed-identities-workload-identity-3602</link>
      <guid>https://dev.to/astaykov/your-agentic-platform-doesnt-need-a-single-secret-managed-identities-workload-identity-3602</guid>
      <description>&lt;p&gt;Every enterprise has a drawer full of static API keys it pretends are under control. They are not.&lt;/p&gt;

&lt;p&gt;A static API key is a bearer credential in the purest sense: it does not know who is using it, does not bind to a caller or a session, and does not expire unless someone remembers to set a date. It grants access to anyone who holds it, full stop.&lt;/p&gt;

&lt;p&gt;And keys never stay where they are supposed to. They travel in plaintext emails, get committed to source control in &lt;code&gt;.env&lt;/code&gt; files that &lt;code&gt;.gitignore&lt;/code&gt; was supposed to catch, get pasted into wiki pages and Slack messages during incident response, and settle into CI/CD pipeline definitions that predate the team's current secrets-management policy. None of this is negligence. It is structural: the tooling makes keys trivially easy to mint and almost impossible to track once they leave the admin console. The result is technical security debt that compounds silently. Keys issued for a proof of concept three years ago are still valid, still embedded in a pipeline nobody touches, still granting day-one access. Revoking them is a game of "what breaks?" that nobody volunteers to play.&lt;/p&gt;

&lt;p&gt;This is the foundation too many organizations are building their agentic platforms on. A foundation made of sand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managed Identities for Azure resources: the first answer
&lt;/h2&gt;

&lt;p&gt;If your workload runs on Azure, the answer has existed for years: &lt;a href="https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview" rel="noopener noreferrer"&gt;Managed Identities for Azure resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A managed identity is a service principal in Microsoft Entra ID whose credentials are entirely platform-managed. Your code never sees a secret, never stores a certificate, never rotates anything. The compute resource requests a token from the local metadata endpoint; Entra issues one. The credential that backs it is inaccessible to anyone, including the team that deployed the workload.&lt;/p&gt;

&lt;p&gt;Three properties make this the default choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complete elimination of static credentials.&lt;/strong&gt; No API key to leak, no connection string to embed, no vault entry to maintain. The identity &lt;em&gt;is&lt;/em&gt; the credential. This is not "better secrets management." It is the absence of secrets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic credential lifecycle.&lt;/strong&gt; Rotation, renewal, and revocation happen without human intervention. No calendar reminders, no runbooks, no incidents when someone forgets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifecycle binding (system-assigned).&lt;/strong&gt; When the Azure resource is deleted, the identity is deleted with it. No orphaned service principals, no zombie credentials. &lt;a href="https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview#managed-identity-types" rel="noopener noreferrer"&gt;User-assigned managed identities&lt;/a&gt; offer an independent lifecycle model for workloads that span multiple resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The conclusion is not nuanced: if your workload runs on Azure, you should be using a managed identity. Every client secret stored in Key Vault "for safety," every certificate rotated on a quarterly schedule, is a choice to do things the hard way when a safer path is right there. Managed identities are not a best practice. They are the baseline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workload Identity Federation: the cross-cloud, cross-provider standard
&lt;/h2&gt;

&lt;p&gt;Managed identities solve the problem when your workload runs on Azure. But workloads do not stay neatly inside one cloud. A GitHub Actions pipeline needs to deploy to Azure. A service on AWS needs to call Microsoft Graph. A Kubernetes cluster on GKE needs to reach an Azure Storage account.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;Workload Identity Federation&lt;/a&gt; (WIF) enters the picture. WIF is not a Microsoft product. It is a pattern built on open standards: &lt;a href="https://openid.net/developers/how-connect-works/" rel="noopener noreferrer"&gt;OpenID Connect&lt;/a&gt; for identity assertions and &lt;a href="https://www.rfc-editor.org/rfc/rfc7523" rel="noopener noreferrer"&gt;RFC 7523&lt;/a&gt; for the JWT bearer token exchange. Instead of handing a workload a long-lived secret, you let it prove who it is using a signed JWT from an identity provider the receiving system already trusts. GitHub, Google Cloud, AWS, Kubernetes, and SPIFFE/SPIRE all issue OIDC-compliant tokens that participate in WIF flows today.&lt;/p&gt;

&lt;p&gt;Microsoft Entra supports WIF in both directions, and this bidirectional capability is what makes the rest of this story possible:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outbound (Entra as issuer).&lt;/strong&gt; Your tenant issues JWTs that external systems can validate and trust, enabling Entra-authenticated workloads to call services outside the Microsoft ecosystem without static credentials. The &lt;a href="https://dev.to/astaykov/your-ai-agent-doesnt-need-an-api-key-entra-agent-id-and-anthropics-workload-identity-federation-el0"&gt;earlier article in this series&lt;/a&gt; explored exactly this: an AI agent using its Entra-issued JWT to authenticate to Anthropic's Claude API through WIF, with no API key involved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inbound (Entra as relying party).&lt;/strong&gt; Your tenant &lt;a href="https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-client-creds-grant-flow#third-case-access-token-request-with-a-federated-credential" rel="noopener noreferrer"&gt;trusts JWTs from external identity providers&lt;/a&gt; and exchanges them for Entra-issued access tokens. This is what lets a GitHub Actions workflow or an AWS Lambda function access Entra-protected resources without a stored secret. The &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation#supported-scenarios" rel="noopener noreferrer"&gt;supported scenarios&lt;/a&gt; span AKS, EKS, GKE, GitHub Actions, Azure DevOps, SPIFFE/SPIRE, and any platform with an OIDC-compliant identity provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Federated Identity Credentials: the inbound trust mechanism
&lt;/h2&gt;

&lt;p&gt;The inbound direction of WIF in Microsoft Entra is implemented through &lt;a href="https://learn.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Federated Identity Credentials&lt;/a&gt; (FICs). A FIC is a configuration object attached to an &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust" rel="noopener noreferrer"&gt;app registration&lt;/a&gt; or a &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust-user-assigned-managed-identity" rel="noopener noreferrer"&gt;user-assigned managed identity&lt;/a&gt; that tells Entra: "when a JWT arrives from this issuer, with this subject, for this audience, treat it as a valid credential and issue an access token."&lt;/p&gt;

&lt;p&gt;Three properties define the trust: &lt;strong&gt;&lt;code&gt;issuer&lt;/code&gt;&lt;/strong&gt; (the external IdP's URL, matched against &lt;code&gt;iss&lt;/code&gt;), &lt;strong&gt;&lt;code&gt;subject&lt;/code&gt;&lt;/strong&gt; (the external workload's identifier, matched against &lt;code&gt;sub&lt;/code&gt;), and &lt;strong&gt;&lt;code&gt;audiences&lt;/code&gt;&lt;/strong&gt; (typically &lt;code&gt;api://AzureADTokenExchange&lt;/code&gt;). All matching is case-sensitive. When an external workload presents a JWT, Entra validates the signature against the issuer's published OIDC keys, checks the claims, and issues an Entra access token. No secret involved. No certificate involved. The trust is cryptographic and scoped to exactly one external workload.&lt;/p&gt;

&lt;p&gt;The mental model: there must be a workload identity in Entra (app registration or managed identity) that &lt;em&gt;trusts&lt;/em&gt; the external token and represents that workload within the Entra ecosystem. The external workload never gets a secret; it gets a trust relationship. (Design note: a maximum of 20 FICs can be configured per app registration or managed identity.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Managed identity as a federated credential: the elegant twist
&lt;/h2&gt;

&lt;p&gt;Managed identities eliminate secrets on Azure. FICs eliminate secrets for external workloads. But what about scenarios where you need an app registration (because the downstream API requires it, because your token needs specific optional claims) and yet you still want zero secrets?&lt;/p&gt;

&lt;p&gt;The answer: &lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity" rel="noopener noreferrer"&gt;configure the app registration to trust a managed identity as its federated credential&lt;/a&gt;. The workload acquires a managed identity token from the local metadata endpoint, presents it to Entra as a FIC on the app registration, and receives an access token scoped to the app. No client secret. No certificate. The managed identity &lt;em&gt;is&lt;/em&gt; the credential. The managed identity handles the credential lifecycle; the app registration handles token shape, optional claims, and API permissions. Each does what it is good at, and no secret sits between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The convergence: Agent Identity Blueprints without secrets
&lt;/h2&gt;

&lt;p&gt;Now bring in &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/concept-agent-id-design-patterns" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint" rel="noopener noreferrer"&gt;Agent Identity Blueprint&lt;/a&gt; is the authentication foundation for one or more agent identities. The blueprint holds the credentials and acquires tokens on behalf of all agent identities created from it. Conditional Access policies applied to the blueprint propagate to every agent identity it parents. It is, by design, the central point where credential management happens for an entire family of AI agents.&lt;/p&gt;

&lt;p&gt;In the simplest deployment model, a blueprint holds a client secret. For production, teams typically upgrade to a certificate. Both are secrets that must be stored, rotated, and protected. Both are liabilities.&lt;/p&gt;

&lt;p&gt;But a blueprint is, at its core, backed by an app registration in Microsoft Entra. And we just established that an app registration can trust a managed identity as its federated credential.&lt;/p&gt;

&lt;p&gt;The implication is direct: configure a managed identity as the federated identity credential on the blueprint's underlying app registration, deploy the agent runtime on Azure compute with that managed identity assigned, and the blueprint acquires tokens using the managed identity token exchange. No client secret. No certificate. No vault. The managed identity, lifecycle-bound to the Azure compute resource, is the only credential in the system.&lt;/p&gt;

&lt;p&gt;Three concepts, designed independently for different purposes, converge into a single architecture: &lt;strong&gt;Managed Identities&lt;/strong&gt; provide the credential-free primitive for Azure compute. &lt;strong&gt;Workload Identity Federation&lt;/strong&gt; extends it across trust boundaries via OIDC and RFC 7523. &lt;strong&gt;Federated Identity Credentials&lt;/strong&gt; bind an external identity (including a managed identity) to an Entra workload identity, replacing secrets with cryptographic trust.&lt;/p&gt;

&lt;p&gt;Applied to an Agent Identity Blueprint, these three deliver a secret-less agentic platform. Not a roadmap item. Not a preview. A production-ready architecture available &lt;em&gt;today&lt;/em&gt;, using generally available constructs in Microsoft Entra ID.&lt;/p&gt;

&lt;p&gt;If you are building an agentic platform in 2026 and your agents still hold secrets, the question is no longer "should we fix this?" The question is "why haven't we?"&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview" rel="noopener noreferrer"&gt;Managed identities for Azure resources overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation" rel="noopener noreferrer"&gt;Workload Identity Federation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/graph/api/resources/federatedidentitycredentials-overview?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Federated Identity Credentials overview (Microsoft Graph)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity" rel="noopener noreferrer"&gt;Configure an app to trust a managed identity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/concept-agent-id-design-patterns" rel="noopener noreferrer"&gt;Microsoft Entra Agent ID design patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint" rel="noopener noreferrer"&gt;Agent Identity Blueprints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc7523" rel="noopener noreferrer"&gt;RFC 7523 — JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openid.net/developers/how-connect-works/" rel="noopener noreferrer"&gt;OpenID Connect&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>microsoftentra</category>
      <category>entraagentid</category>
      <category>aiagents</category>
      <category>wif</category>
    </item>
  </channel>
</rss>
