How to see what apps can really do in your tenant
If you’ve ever opened microsoft entra id (azure ad) and clicked through enterprise applications → permissions, you’ve seen the comforting illusion of control: a list of “api permissions” that looks finite, reviewable, and mostly harmless.
In real incidents, that list is rarely the whole story.
The permissions you see (requested permissions on an app registration) are not always the permissions that are granted (consented in your tenant). The permissions that are granted are not always the permissions that are usable (because of conditional access, workload identity constraints, or missing assignments). And the permissions that are usable are not always the permissions that are used (because many apps are stale, abandoned, or over-scoped “just in case”).
Auditing azure ad app permissions is the discipline of closing those gaps—so you can answer, with evidence:
- which apps and service principals exist in the tenant
- what they can access (delegated + application permissions)
- who granted that access (user vs admin, tenant-wide vs per-user)
- whether that access is still necessary
- what to revoke, constrain, or govern next
That matters more now than even a year ago. OAuth-based compromise patterns keep evolving (consent phishing is still thriving), and recent research write-ups keep reminding defenders that attackers prefer access paths that don’t look like “password theft.” Microsoft’s own guidance focuses heavily on reducing consent risk and controlling app access.
This article goes beyond the “click here in the portal” version. You’ll get first-principles clarity, an expert-grade technical audit runbook, and a practical comparison of the best audit methods—portal, Graph, Defender app governance, and tool-based approaches.
what “app permissions” really are (and why most audits miss the point)
At the core, Entra app access is built from two primitives:
- An identity for the app in your tenant
That’s the service principal (enterprise application). It’s the “instance” of an app in your directory, where assignments, consents, and policies land. - An authorization grant that links that identity to resource access
In Microsoft terms, this is mainly:- delegated permission grants (OAuth scopes) represented by oAuth2PermissionGrant objects
- application permission assignments (app roles) represented by appRoleAssignments (to the service principal)
Most “surface audits” only look at the app registration and what permissions are configured to be requested. But attackers, risky SaaS tools, and “shadow IT” don’t care what was requested. They care what was granted in your tenant.
So the first-principles rule is simple:
Requested permissions are intent. Granted permissions are reality.
And your audit should be built around reality.
the comparison that actually matters: four ways to audit azure ad app permissions
You can audit in at least four credible ways. The difference is coverage and truthfulness, not convenience.
1) entra admin center (fastest, least complete)
Best for: quick spot checks, explaining to stakeholders, small tenants.
Weakness: hard to do tenant-wide rigor; doesn’t naturally produce a complete inventory with delegated + app-only grants and “who consented what”.
It can show granted permissions per app and allow revocation actions. Microsoft’s docs explicitly describe reviewing and revoking permissions via the admin center. (GitHub)
2) microsoft graph (most complete, most defensible)
Best for: real audits, repeatable reporting, CI-style governance.
Weakness: you must model the data correctly (service principals, grants, role assignments), and permission name mapping takes effort.
Graph has first-class resource types and endpoints for delegated grants (oAuth2PermissionGrant) and can enumerate service principals and relationships.
3) defender for cloud apps “app governance” (best operational signal)
Best for: ongoing monitoring, risk scoring, behavioral detection, remediation workflows.
Weakness: licensing/enablement, and it’s more “governance + detection” than “compliance-style inventory”.
Microsoft positions app governance as visibility and policy management for OAuth-enabled apps across Entra and others.
4) purpose-built tooling (fast reporting, opinionated risk views)
Examples include:
- microsoft identity tools consent grant reporting (Export-MsIdAppConsentGrantReport) (azuread.github.io)
- third-party identity/security suites (including ManageEngine’s governance/security tooling)
Best for: speed, dashboards, stakeholder-friendly outputs.
Weakness: you still need to understand the primitives to validate tool output and avoid false confidence.
A mature program often uses Graph for truth, Defender for signal, and tools for workflow/reporting.
The irreducible truths behind app permission risk
To audit well, you need a few “physics laws” of Entra permissions.
truth 1: delegated vs application isn’t a detail—it’s the whole threat model
- Delegated permissions (scopes) act as a user. If a user has access to data, the app can access it too—within the granted scopes.
- Application permissions (app roles) act as the app. No user required. This is where tenant-wide data exfiltration stories usually begin.
That distinction is the difference between “user tricked into consenting” and “app can read every mailbox.”
Microsoft’s own identity platform documentation frames permissions and consent around these consented authorizations and scenarios.
truth 2: “admin consent” is a security boundary and a foot-gun
Admin consent is meant to prevent users from granting high-impact access. But many tenants accidentally convert a user-specific need into a tenant-wide grant by consenting “on behalf of the organization.”
That’s not hypothetical—practitioners complain about exactly this workflow friction and approval gating in the wild.
truth 3: grants persist longer than your memory
Even if an app is “no longer used,” its service principal and consent grants often remain. Those stale grants are a common source of quiet risk—especially if secrets/certs are also left active.
truth 4: least privilege is not a slogan; it’s an engineering constraint
Least privilege in Entra means:
- minimizing breadth (which resources)
- minimizing depth (which actions)
- minimizing duration (how long access exists)
- minimizing distribution (who can consent/assign)
User consent settings and admin consent workflows are explicit controls Microsoft recommends configuring to reduce risk.
Build a defensible tenant-wide app permission inventory
This section is deliberately technical and designed to be copied into your internal audit procedure. It focuses on the three questions that matter:
- what exists (inventory of service principals and apps)
- what’s granted (delegated grants + app role assignments)
- what’s risky or stale (prioritization + next actions)
step 0: decide what you’re auditing (scope that prevents nonsense)
Be explicit:
- tenant scope: single tenant vs multi-tenant landscape
- app scope: include enterprise apps + managed identities + first-party microsoft service principals
- permission scope: delegated + application, and whether you also want directory roles assigned to service principals
- time scope: “current state” vs “current + last 90 days usage”
A good default for most orgs:
- include all service principals except Microsoft first-party unless they have elevated permissions
- include both delegated grants (oAuth2PermissionGrants) and application permissions (appRoleAssignments)
- include owners and credential state (secrets/certs)
- attempt a usage signal (sign-ins/app governance) for prioritization
step 1: connect using microsoft graph powershell with appropriate read scopes
You need read access to applications/service principals and the permission grants. Start with least privilege, then expand.
Example baseline (you may need more depending on what you pull):
Application.Read.AllorDirectory.Read.All- possibly
AuditLog.Read.Allif you correlate with logs later
Microsoft documents Graph PowerShell cmdlets like Get-MgServicePrincipal and required permissions.
step 2: build the inventory spine: service principals are your ground truth
Your report should key on service principal id, not app name. Names change; IDs don’t.
Collect fields that support triage:
- displayName
- appId (application id)
- servicePrincipalType (Application / ManagedIdentity / etc.)
- publisherName / verifiedPublisher
- signInAudience (if you pull application objects too)
- tags (WindowsAzureActiveDirectoryIntegratedApp, etc.)
- accountEnabled
- createdDateTime
Why? Because your audit needs to answer “is this internal, marketplace, or unknown?” fast.
step 3: collect application permissions (app roles assigned to the service principal)
Application permissions are typically represented as app role assignments to the resource service principal (for example: Microsoft Graph resource SP).
Conceptually:
- client SP = the app in your tenant
- resource SP = the API (Microsoft Graph, SharePoint, Exchange Online)
- appRoleAssignment = “client gets role X on resource”
You’ll pull assignments and then map role IDs to names by looking up the resource’s app roles.
A practical trick: for Microsoft Graph, the resource app id is well-known and used in Azure CLI documentation examples.
step 4: collect delegated grants (oAuth2PermissionGrants)
Delegated grants are represented by oAuth2PermissionGrant objects. Graph supports listing them.
Key fields you must interpret correctly:
clientId(service principal receiving the grant)resourceId(service principal of the API)scope(space-separated scopes)consentType:AllPrincipals= tenant-wide delegated consent (admin consent)Principal= per-user consent
principalId(present for per-user grants)
This is where many audits fail: they list scopes but don’t distinguish tenant-wide vs per-user, which changes your risk profile dramatically.
step 5: map “ids to human names” so humans can review the report
Raw output is unreadable unless you translate:
resourceId→ resource service principal displayName (e.g., Microsoft Graph)- role IDs (appRoleId) → role value + displayName
- scope strings → already human-readable but still need grouping by resource
If you want a shortcut for Graph permission meaning, tools like Graph Permissions Explorer can help you understand what a permission implies, and Microsoft Identity Tools can generate reports that categorize privilege. (graphpermissions.merill.net)
step 6: classify risk using a simple, repeatable rubric
Avoid subjective “this feels scary.” Use a rubric that’s explainable.
Example classification:
critical (usually needs explicit business justification)
- application permissions that can read/write mail, files, directory, identity providers, policies
- tenant-wide delegated consents with broad scopes
high
- directory-wide read scopes (still sensitive)
- offline_access + broad resource scopes for user data
medium
- narrow scopes limited to one workload, read-only
low
- basic profile, openid, email (still can be abused, but smaller blast radius)
Microsoft’s own community Q&A shows how broad something like Directory.Read.All is perceived, and why admins question it. (Microsoft Learn)
step 7: add “governance fields” that decide what you do next
Your report should include:
- who consented (user vs admin; tenant-wide vs per-user)
- when granted (if you can infer via logs; otherwise “unknown”)
- credential status:
- does the app have active secrets/certs?
- are secrets expiring soon?
- ownership:
- who owns the app registration / enterprise app?
- usage signal:
- last sign-in (service principal sign-in logs)
- Defender app governance activity (if enabled)
This is how you avoid spending a week debating an app nobody uses.
step 8: decide remediation actions that match how access was granted
Remediation is different for each case:
- stale app with app-only permissions: remove app role assignments first, then disable or delete service principal, then rotate/remove credentials.
- user-consented risky app: remove the delegated grant (oAuth2PermissionGrant), review user consent settings, and hunt for similar apps.
- legitimate integration but over-privileged: replace broad permissions with narrower ones, and enforce admin consent workflow for future requests.
Microsoft’s Entra guidance explicitly supports reviewing and revoking permissions and managing user consent settings and admin consent workflows.
step 9: close the loop with preventative controls (otherwise your audit decays)
A one-time audit is a snapshot. You want drift control:
- configure user consent (limit or disable, and restrict to verified publishers where appropriate)
- enable admin consent workflow so users request and reviewers approve
- use Defender for Cloud Apps app governance for ongoing visibility and policy enforcement
- add a quarterly or monthly Graph-based export and diff
- alert on new high-risk grants
This is also where practitioners converge: many orgs don’t want to “turn off all consent,” they want a controlled request/approve pathway.
wrap-up: the point of the audit is control, not reporting
A real audit outcome isn’t a spreadsheet. It’s a tenant where:
- apps have the minimum permissions needed
- high-risk grants are rare and justified
- new app access goes through workflow
- suspicious OAuth behavior triggers response
- stale apps don’t accumulate for years
If you want a practical next step that also helps with lead generation: publish (and offer as a download) a tenant app permission audit worksheet with:
- a risk scoring rubric
- a review log template
- a remediation decision tree
- a “before/after” diff tracker
Add a short form: “Send me the worksheet + the PowerShell/Graph query pack.”
For readers on windows-active-directory.com, this topic pairs naturally with adjacent guides like:
- active directory and entra identity fundamentals
- conditional access strategy
- privileged identity management and role governance
- incident response playbooks for identity compromise
- kerberos/ntlm modernization (hybrid identity dependencies)
And if you’re using ManageEngine for identity governance or M365 security operations, this is a good place to reference their governance workflows for approvals, reviews, and reporting—while keeping Graph-based exports as your ground truth.
external references
- Microsoft identity platform: permissions and consent overview (Microsoft Learn)
- Microsoft Graph: oAuth2PermissionGrant resource and list endpoint (Microsoft Learn)
- Microsoft Entra: configure user consent + admin consent workflow (Microsoft Learn)
- Microsoft Defender for Cloud Apps: app governance (Microsoft Learn)