Authorization and permissions in Entra Agent ID
Which directory roles an agent may hold, which Graph permissions are hard-blocked, and how inheritable permissions work.
Why this matters
Entra's agent authorization model looks familiar (Graph permissions, Entra directory roles) but has three hard rules you must know before day 1:
- Many high-privilege Microsoft Entra roles are blocked for agent identities — you can't even consent to them.
- A specific set of Microsoft Graph permissions is blocked —
Application.ReadWrite.All,User.ReadWrite.All,RoleManagement.ReadWrite.All,Directory.AccessAsUser.All. - Permissions can be assigned in two places — directly on an agent identity, or on the blueprint (with cascading to all children via inheritable permissions). Getting these two levels right is the difference between "clean rollout" and "we re-consented 200 agents individually".
Cross-ref: Lesson 6.1 (Per-tool authz + policy as code) covers OPA/Cedar/capabilities generically. This lesson is how Microsoft answers the same question — via the directory + Graph consent model.
Learning objectives
- Recite the four categories of agent permissions (Azure roles, Entra roles, delegated Graph, application Graph) and pick the right one per use case.
- Know the blocked Entra roles and blocked Graph permissions cold — you will be asked at review time.
- Understand
requiredResourceAccessvs inheritable permissions and use them together. - Reason about static vs dynamic consent and permission inheritance.
- Use the permission cheat sheet to design least-privilege for a real agent.
1. Four places to grant access — pick per resource
| Resource being accessed | Grant type | Example |
|---|---|---|
| Azure resource (Key Vault, Storage, Cosmos DB, App Config) | Azure RBAC role on the resource / RG / subscription | Give agent identity Key Vault Secrets User on kv-prod-eu |
| Entra directory operation (read users, read groups) | Entra directory role (from the allow-list) | Assign Directory Readers to agent identity |
| Microsoft 365 data as a specific user | Delegated Microsoft Graph permission (Mail.Read) | Alice consents; agent OBO into Alice's mailbox |
| Microsoft 365 data across the tenant | Application Microsoft Graph permission (User.Read.All) | Admin consents; agent app-only reads all users |
Rule: prefer the narrowest scope that works. Azure RBAC on a specific vault beats a tenant-wide Graph app permission every time.
2. Blocked Microsoft Entra directory roles
Agent identities cannot be assigned any role that gives tenant-level control. Neither users nor administrators can consent to these:
Global AdministratorPrivileged Role AdministratorUser AdministratorApplication AdministratorCloud Application AdministratorPrivileged Authentication Administrator- Most other role assignments capable of granting further roles or resetting credentials.
You also cannot:
- Assign a custom Entra role to an agent identity.
- Add an agent identity to a role-assignable group.
Agent identities may be assigned (highlights — full list on Microsoft Learn)
Directory Readers,Global Reader,Reports Reader,Security Reader- Workload-specific admin roles:
Teams Administrator,Exchange Administrator,SharePoint Administrator,Compliance Administrator,AI Administrator,Fabric Administrator,Power Platform Administrator,Windows 365 Administrator, etc. - Insight / attribute / message-centre / branding roles for narrow admin tasks.
- Microsoft's own new agent-management roles:
Agent ID Administrator,Agent ID Developer.
Rule of thumb: if the role exists in the allow-list, it's fine; if not, use Graph permissions or Azure RBAC on specific resources instead. The allow-list evolves — check the Learn page for the current copy.
3. Blocked Microsoft Graph permissions
Regardless of admin consent, these Graph permissions are permanently unavailable to agent identities:
| Blocked permission | Why blocked |
|---|---|
Application.ReadWrite.All | Would let an agent create / modify other apps, including new agents with any permission set. Full-tenant compromise vector. |
RoleManagement.ReadWrite.All | Would let an agent grant itself or anyone else any role, including blocked ones. Effective escalation to Global Admin. |
User.ReadWrite.All | Full write control over every user (create, delete, reset password, disable). Escalation vector via password reset. |
Directory.AccessAsUser.All | Grants the token bearer directory-wide access as the signed-in user — bypasses agent's own scope model entirely. |
These are hard-blocked; no override, no exception, no support ticket. Design accordingly — if the agent needs "manage users", get a real admin to run that flow manually.
Permissions that stay on the table
Anything user-scoped or narrowly-scoped is fine:
Mail.Read,Mail.Send,Files.Read,Files.ReadWrite,Calendars.Read— delegated, per-user consent.User.Read.All(read-only) — app-only, admin-consented, read-only enumeration.Sites.Selected— targets a specific SharePoint site (very common for RAG agents).Group.Read.All,TeamworkTag.Read.All, etc. — read-only tenant views.
If you find yourself asking for a *.ReadWrite.All on Users / Applications / RoleManagement, the correct answer is redesign — use narrower delegated permissions or run the sensitive step out-of-band with a real admin.
4. Static vs dynamic consent
Microsoft's model has two consent styles. Both matter.
4.1 Static consent — requiredResourceAccess on the blueprint
The blueprint declares up-front: "these are the APIs + scopes this agent class needs". Admins see this list during onboarding review.
{
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000", // Microsoft Graph
"resourceAccess": [
{ "id": "570282fd-fa5c-430d-a7fd-fc8dc98a9dca", "type": "Scope" }, // User.Read (delegated)
{ "id": "62a82d76-70ea-41e2-9197-370581804d09", "type": "Role" } // Group.Read.All (application)
]
}
]
}Rule: requiredResourceAccess is a declaration, not a grant. An admin still consents; the declaration is your bill of materials so the admin knows what they're approving.
4.2 Dynamic consent — asked at token-request time
The sidecar / MSAL can ask for a permission the blueprint didn't declare, provided:
- The permission is explicitly named in the token request, and
- The blueprint principal has been granted that permission.
Dynamic consent is not visible in the up-front review. That's intentional (for optional / infrequent scopes) and dangerous if abused. Rule: any permission you always need goes in requiredResourceAccess; only truly optional ones stay dynamic.
5. Inheritable permissions — the deployment lever
This is Entra Agent ID's answer to "we have 200 identical agents in 40 tenants; the admin does not want to re-consent 200×40 times".
5.1 How it works
On the blueprint you declare which resource apps are eligible for inheritance:
{
"inheritableResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000", // Graph
"delegatedInheritancePattern": "All", // all delegated scopes flow down
"applicationInheritancePattern": "None" // NO app roles flow down
}
]
}An admin grants a permission once, on the blueprint principal. From that moment, every existing and future agent identity from that blueprint receives that permission in its access tokens automatically. No per-identity consent screen.
Two conditions must both be true for inheritance to actually flow:
- The permission was granted via static consent (
requiredResourceAccess) or dynamic consent with the permission explicitly named. - The resource app is listed as inheritable on the blueprint.
Miss either condition → no inheritance.
5.2 The declaration / grant / inheritance cheat sheet
| Layer | What it is | Who controls it | Effect |
|---|---|---|---|
requiredResourceAccess | Declared APIs + permissions | Developer (blueprint) | Visible at consent review — does not grant |
| Inheritable permissions list | Resource apps eligible for cascade | Developer (blueprint) | Enables cascade — does not grant |
| Consent on blueprint principal | Actual grant | Tenant admin | If resource app is inheritable → all children receive it |
| Direct consent on agent identity | Per-identity grant | Tenant admin | Grants that specific identity only |
| Effective token permissions | Merged inherited + direct | Platform (at token issuance) | What the agent can actually do |
5.3 Design patterns
| Situation | Pattern |
|---|---|
| Baseline permissions all agents of this class need | requiredResourceAccess + inheritable + admin consent on blueprint principal |
| Optional feature added later | Inheritable list only (empty requiredResourceAccess) — admin consents when feature is enabled |
| Sensitive privileged agent | requiredResourceAccess without inheritable — force per-identity admin consent each install |
| Different needs per tenant | Both declared, admin picks which to grant per tenant |
5.4 Non-obvious: inherited permissions are invisible in the admin UI
Inherited scopes / roles do not show up on the agent identity's permission page in the Entra admin center or in Graph queries for that identity. They only appear in the runtime token. Auditors don't see them either — you have to teach reviewers to look at the blueprint principal's grants + the inheritable list.
This is a common source of "why does this agent have Mail.Send? I never granted it" tickets. Answer: the blueprint principal was granted it and the Graph resource app is inheritable.
6. Access packages — governed self-service (Lesson 10.7 will go deeper)
For agent identities that need periodic re-approval or standardised access bundles, use access packages from Entra ID Governance:
- Agent (or sponsor) requests an access package.
- Approver in workflow approves.
- Agent identity is granted a set of security groups + Graph app perms + Entra roles.
- Access is time-bound. Sponsor gets renewal notifications.
Rule: for recurring access with review, use access packages. For always-on foundational access, use direct assignment on the identity (or inheritable on the blueprint).
7. Least-privilege design walkthrough — worked example
Take a MTN-CRM-HelpdeskV2 agent:
- Read tenant users (to look up requesters) → Graph
User.Read.Allapplication perm on the blueprint principal, inheritable=all. - Read the requester's mailbox to see recent tickets by email → Graph
Mail.Readdelegated perm, granted on the blueprint principal, inheritable=all, invoked via OBO. - Read Azure Key Vault for a partner API secret → Azure RBAC
Key Vault Secrets Useron the specific vault, granted per environment (dev/prod) directly to the environment-specific agent identities, not on the blueprint (Azure RBAC on blueprint isn't supported anyway). - Post to a specific Teams channel as "Helpdesk Bot" → agent's user account is licensed + added to the channel; delegated
ChannelMessage.Sendvia the agent user flow. - NOT allowed:
Directory.AccessAsUser.All(blocked),User.ReadWrite.All(blocked),Application.ReadWrite.All(blocked). Anything that would need those goes to a human admin.
Result: no .All write permissions. All tenant data written on behalf of a specific user (Alice) or through the agent user (helpdesk-bot@…). Every Azure resource access is on a named resource. This is what you show at review.
8. Common pitfalls
- Trying to grant
Global Readerinheritably.Global Readeris a directory role, not a Graph permission — you assign it directly on each identity (or on a group the identity is in). - Requesting
.defaultscope by muscle memory. Fine for app-only tokens; wrong when you want an explicit subset of dynamic-consent scopes. - Marking Graph as inheritable and dumping every scope into
requiredResourceAccess. Consent review will flag it. Split into essential-vs-optional; keep optional dynamic. - Forgetting to consent on the blueprint principal after publishing. The blueprint has a
requiredResourceAccesslist, the tenant has zero grants. Agents get 401 on Graph. - Assigning Azure RBAC roles to the blueprint. Not supported — assign to individual agent identities.
- Adding an agent identity to a role-assignable group to bypass the blocked-role list. Not allowed — agent identities cannot be members of role-assignable groups.
- Confusing agent identity permissions with agent user account permissions. The user account gets its own guest-like permissions, plus whatever licence-based Microsoft 365 permissions the licence grants. Don't over-provision the user account.
- Not auditing inherited permissions. Set a quarterly job: for every blueprint, log the grants on the blueprint principal + the inheritable list; diff against last quarter.
9. Hands-on lab (2 h)
Prereqs: the blueprint + agent identity from Lesson 10.2, the sidecar from Lesson 10.3.
- On the blueprint, set
requiredResourceAccesstoUser.Read(delegated) +Group.Read.All(application). Verify withGet-MgApplication. - Mark Microsoft Graph as inheritable (delegated=All, application=None).
- As an admin, consent both permissions on the blueprint principal.
- Acquire an autonomous token for the agent identity — confirm
rolescontains noGroup.Read.All(application inheritance was set to None). - Change
applicationInheritancePatterntoAll; re-run — nowGroup.Read.Allshould appear inroles. - Try to assign
User Administratorrole to the agent identity — expect a policy error citing blocked role. - Try to grant
Application.ReadWrite.Allon the blueprint principal — expect it to fail. Log the error message; you'll see it in production tickets. - Assign
Key Vault Secrets Useron a specific test Key Vault to the agent identity directly (Azure portal → Key Vault → Access control). Verify the agent can read a secret using the autonomous token.
10. Self-check
- Name the four blocked Microsoft Graph permissions. Why each is blocked.
- Why is
Global Administratorblocked for agents? - What's the difference between
requiredResourceAccessand inheritable permissions? - If an admin grants
Mail.Readon the blueprint principal and Graph is inheritable, what does the agent identity's Entra admin-center permission page show? - When would you deliberately mark a resource app as not inheritable?
- Which permission model (Azure RBAC / Entra role / delegated Graph / app Graph) is right for reading a specific Cosmos DB collection?
11. References
- Authorization in Microsoft Entra Agent ID
- Inheritable permissions
- Best practices for Microsoft Entra Agent ID
- Vendor-neutral Lesson 6.1 — Per-tool authz + policy as code.
- Vendor-neutral Lesson 6.2 — Human-in-the-loop approvals.
Sign in to save your progress and earn badges.