There’s one line we hear again and again: “If I grant an app delegated Graph permissions with admin consent, the app can do everything in the tenant.”
It’s especially confusing when you start working with Microsoft Graph and Entra ID. If an app gets a delegated scope like PrivilegedAccess.ReadWrite.AzureADGroup, can anyone in the tenant use it? The short answer: no.
The insight that changes everything: delegated permissions always run in the context of the signed-in user. The user’s existing Entra role remains a gatekeeper, just as much as the app’s permissions.
Delegated vs. application permissions: what’s the difference?
Delegated permissions (user + app). In this scenario:
- The app acts on behalf of a signed-in user.
- The app must have the correct delegated scope, and the user must hold the Entra role needed to perform the action.
- If either is missing, the app’s scope or the user’s role, the call fails with insufficient privileges.
A real test: we ran Graph CLI with PrivilegedAccess.ReadWrite.AzureADGroup. As a normal user, every call failed. As Global Admin, it all worked. Delegated permissions don’t elevate users; they only let the app do what the user could already do by hand.
Application permissions (app alone). No user is involved here: the app runs under its service principal identity. The action succeeds based solely on the permissions granted to the app, regardless of any user role.
Example: an app with Group.ReadWrite.All as an application permission can create or delete groups with no user signed in at all. That’s why application permissions must be treated like privileged service accounts: they bypass user checks entirely.
Entra directory roles: the overlooked link
It’s tempting to think API permissions alone decide what gets done, but that’s only half the story. In the delegated model, the user’s Entra role matters just as much.
| Delegated Graph permission | Required Entra roles |
|---|---|
| Group.ReadWrite.All | Global Admin, Groups Admin, Directory Writers |
| RoleManagement.ReadWrite.Directory | Global Admin, Privileged Role Administrator |
| PrivilegedAccess.ReadWrite.AzureADGroup | Global Admin, Privileged Role Administrator |
| Directory.ReadWrite.All | Depends on the object: e.g. User Administrator for users; all objects only Global Admin |
Even with the app permission in place, you’re stuck if the user doesn’t hold one of these roles. Delegated only works when the app’s permission and the user’s role line up.
Consent models: user vs. admin
User consent:
- Each user approves delegated scopes individually when they sign in.
- Tenant admins can disable or restrict it.
Admin consent:
- A Privileged Role Administrator can pre-approve any permission for the whole tenant. Cloud Application Administrators and Application Administrators can approve everything except Microsoft Graph application permissions.
- Users no longer see consent prompts.
- The catch: it does not bypass the user’s required role. A non-admin user is still blocked from privileged actions, even though the permissions are “consented”.
Security risks and misuse
These are the most common mistakes we see:
- Over-using application permissions just because they seem simpler.
- Believing that admin consent means tenant-wide superpowers.
- Not auditing apps that hold broad scopes like Directory.ReadWrite.All.
The danger isn’t in delegated permissions. It’s in misunderstanding how they work, or over-provisioning application permissions without oversight.
Best practices
- Prefer delegated permissions where possible: they’re safer by nature because they inherit the user’s least privilege.
- Be careful with application permissions: treat them like privileged service accounts.
- Monitor and audit which apps hold high-impact Graph scopes.
- Use admin consent sparingly, and only for trusted apps.
- Review service principals with app-only permissions regularly, and know what they can really do.
Dynamic vs. static consent
According to Microsoft’s documentation, delegated permissions can be granted dynamically at runtime (incremental consent). An app can request additional scopes as needed, and the user decides in the moment.
Application permissions don’t have this flexibility: they’re static and must be pre-approved by admins. That’s another reason delegated permissions are often the better choice.
Conditional Access: another difference
Conditional Access policies apply to delegated permissions, because a user is signing in. If a policy requires MFA, device compliance or specific networks, it applies.
With application permissions there’s no user sign-in, so regular Conditional Access policies don’t apply. You can block service principals by location or risk with Conditional Access for workload identities, but only for single-tenant apps registered in your tenant, and only with a Workload Identities Premium license. SaaS apps and managed identities aren’t covered, an often-overlooked governance gap.
The bottom line
- Delegated = user + app, constrained by the Entra role.
- Application = the app alone, governed by its service principal.
- Admin consent removes prompts, not role checks.
If you take one thing away: delegated permissions don’t elevate users; they respect their boundaries.
App permissions and consent settings are easy to lose track of. Griffin31 checks your tenant’s settings continuously and shows you what to fix first.