HomeNewsletterCommunityToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog
Security Entra IDEnterprise AppsOAuthSecurityPowerShellZero Trust

That AI Tool You Just Gave 'Read/Write All' to Entra and Intune — Would You Even Notice?

IA
Imran Awan
16 July 2026

Earlier this week, an admin posted on r/sysadmin describing something that will make most of us wince a little: their organisation had just adopted a third-party AI-powered ITSM platform, and during onboarding the vendor's setup wizard asked for admin consent to read and write across Active Directory, Entra ID, Intune, and — in their words — "all Microsoft 365 services." Not read-only. Not scoped to a single mailbox or a single security group. Full read/write, tenant-wide, indefinitely.

The replies were the more interesting part. Several admins said some version of the same thing: they had approved something similarly broad for a different vendor two or three years earlier, and nobody on the current team could say — off the top of their head — exactly what permissions that app still holds today, whether the vendor is still the same company they originally signed a contract with, or whether a single person has looked at that consent grant since the day it was approved.

So here is the direct question this post is built around: would you have caught this in your own tenant? Not hypothetically. If you opened Entra ID right now and reviewed every enterprise application holding admin-consented permissions, would you know which ones hold Directory.ReadWrite.All, which ones can silently push arbitrary Win32 app deployments to every Intune-managed device, and which ones were approved by an admin who left the organisation eighteen months ago?

Most admins can't answer that with confidence, and it isn't because they're careless. It's because the app consent model in Entra ID was built to make approving access frictionless — a single click during a rushed vendor onboarding call — while almost nothing in the platform was built to make you revisit that click afterwards. This post works through why that gap exists structurally, how to manually spot-check a single app in the portal, and then hands you a PowerShell script that audits every enterprise application in your tenant against a defined list of genuinely dangerous permissions, in one pass.

The problem — a consent grant is a standing, silent trust relationship

Every time a user clicks "Accept" on a "Sign in with Microsoft" prompt, or an administrator clicks "Accept" on an admin-consent prompt during onboarding, Entra ID creates something that quietly outlives that single click by years: a service principal in your tenant, holding a defined set of Microsoft Graph permissions tied to that vendor's application. That grant does not expire. OAuth 2.0, as implemented in Entra ID, has no native concept of "this access is valid for 12 months and then requires re-approval." Once granted, a permission stands until a human being goes into Entra ID and deliberately removes it.

That alone would be manageable if something in the platform nudged admins to revisit these grants periodically. By default, nothing does. There is no built-in alert if the vendor behind that app is later acquired by a company you have never vetted. There is no alert if the vendor suffers a supply-chain compromise and an attacker starts using its already-trusted app registration to pull data out of your tenant using permissions your organisation approved two years earlier. There is no alert if the vendor simply turns out, on closer inspection, to be a five-person startup whose app over-requests permissions "just in case, for future features." The trust relationship is silent by design — it was never built with a review cycle in mind.

What makes this genuinely dangerous, rather than just untidy, is the distinction between delegated and application permissions. A delegated permission only operates while a specific user is signed in, and is bounded by whatever that particular user is already allowed to do. An application permission is a different animal entirely: it gives the app its own standing identity in your tenant, and that identity can call Microsoft Graph with zero signed-in user involved — 24 hours a day, 7 days a week, regardless of whether anyone at the vendor, or in your organisation, is actively using the integration at that moment.

That is exactly the category of permission the Reddit thread was describing. An AI ITSM platform requesting broad "read/write to Active Directory, Entra ID, Intune, and Microsoft 365" during onboarding is, translated into Graph terms, very likely asking for application permissions such as Directory.ReadWrite.All, RoleManagement.ReadWrite.Directory, and DeviceManagementApps.ReadWrite.All. Those three permissions alone let an app create and modify user accounts, assign or remove Entra ID directory roles — including, in the worst case, Global Administrator — and push arbitrary application deployments to every Intune-managed device in the estate. None of that requires a human being at the vendor to be doing anything at all at the moment it happens; the app simply has that access, permanently, because someone clicked Accept once.

⚠ Warning: Do not revoke a permission grant for a production-critical app without confirming with its owner first. Enterprise apps holding broad Graph permissions are very often wired into real, load-bearing integrations — HR sync jobs, backup agents, SIEM connectors, ticketing systems. Pulling a permission an app is actively using will break that integration, sometimes silently, sometimes at 2am. Treat every finding from the audit in this post as the start of a conversation with the app owner, not a delete button.

Why it happens — the app consent framework nobody reads twice

To see why this gap exists structurally, it helps to separate four concepts that get casually lumped together under "app permissions" in everyday conversation, but are actually distinct layers inside Entra ID's consent framework.

Delegated permissions vs application permissions

This is the single most important distinction in the whole framework, and it is worth internalising properly before you look at a real tenant.

AspectDelegated permissionApplication permission
Runs asThe signed-in userThe app itself, no user context
Bounded byWhat that user can already doWhatever the permission grants, full stop
Active with no one signed inNoYes — 24/7
Consent requiredUser or admin, depending on riskAdmin only, always
Typical use caseAn app acting on behalf of the person using itA backend service, daemon, or scheduled job

Application permissions always require admin consent — Entra ID will not let an individual user grant one to an app on their own. That is a meaningful safety rail. The problem is that "admin consent" in practice often means one admin, in one onboarding call, approving a bundle of permissions presented by the vendor's consent screen, without necessarily reading each one against what the product genuinely needs.

Admin consent vs user consent

Admin consent applies tenant-wide and covers any permission, including application permissions. User consent is narrower by design — Microsoft restricts which delegated permissions a regular user is even allowed to approve for themselves, based on a defined "low-risk" list (things like reading the signed-in user's own profile or calendar). The idea is that a user should never be able to grant an app access to company-wide data purely by clicking through a sign-in prompt on their own.

Enterprise applications vs App registrations

These two objects are related but not identical, and mixing them up is one of the most common reasons an admin can't find the app they're looking for.

ObjectWhat it representsWhere it lives
App registrationThe global definition of an app — its name, redirect URIs, and the permissions it is coded to requestOwned by whoever created it. For a third-party SaaS vendor, that's the vendor's own tenant, not yours
Enterprise applicationThe local instance of that app inside your tenant — the service principal — the object that actually holds the permission grants applying to your dataYour tenant, created automatically the first time someone consents to the app

This is exactly why searching "App registrations" for a vendor's product usually turns up nothing. The app registration itself lives in the vendor's own Entra tenant. What you have, and what you need to review, is the enterprise application object — the local copy of that app inside your tenant that actually holds the permission grant.

Default user consent settings — the quiet door

Even with application permissions locked behind admin consent, many tenants still ship with a setting that lets end users approve a defined set of low-risk delegated permissions for themselves, with no admin ever seeing the request. This lives at Entra ID › Enterprise applications › Consent and permissions › User consent settings, and in a large number of tenants it is still set to something like "Allow user consent for apps from verified publishers, for selected permissions" rather than "Do not allow user consent." On its own, a single low-risk delegated permission looks harmless. The risk is combination: a permission like offline_access paired with something like Mail.Read gives an app a long-lived refresh token and ongoing read access to that one user's mailbox — approved entirely by the user, with zero admin visibility, the moment they click through a slick-looking sign-in screen linked from a phishing-adjacent email.

Verified publisher status — necessary, not sufficient

Microsoft's publisher verification process confirms that the developer behind an app registration is a real, Microsoft Partner Network-verified organisation, and links that identity to the Entra ID app object with a visible badge. It is a genuinely useful signal — an unverified publisher requesting broad permissions during a rushed vendor onboarding call is a real red flag, and it's exactly the kind of detail that gets skipped when a project deadline is the only thing anyone in the room is thinking about.

⚠ Gotcha: A "verified publisher" badge means Microsoft has confirmed the developer's identity through the Microsoft Partner Network — it is an identity check, not a permission-appropriateness check. Verified publishers can, and do, over-request permissions. A checkmark next to a vendor's name tells you who they are. It does not tell you whether what they're asking for is proportionate to what their product actually needs.

How to verify — spot-checking one app in the Entra portal

Before reaching for PowerShell, it's worth knowing how to check a single application by hand. This is the fastest way to answer "what does this new vendor's app actually hold" the moment a contract gets signed, or the moment a colleague asks "wait, do we actually know what that thing can do?"

  1. Sign in to the Entra admin centre as at least a Cloud Application Administrator
  2. Browse to Identity › Applications › Enterprise applications
  3. Search for the app by name and select it
  4. Select Permissions from the left-hand navigation
  5. Review both tables on the page: Admin consent (application and delegated permissions your organisation's admin approved for all users) and User consent (delegated permissions individual users approved for themselves, if user consent is enabled)
Entra ID — Enterprise applications — AI ITSM Platform — Permissions
⚠️ Publisher not verified — this developer's identity has not been confirmed by Microsoft
Directory.ReadWrite.All
Application · Read and write directory data
Admin consent granted
DeviceManagementApps.ReadWrite.All
Application · Read and write Microsoft Intune apps
Admin consent granted
User.Read
Delegated · Sign in and read user profile
Admin consent granted

That single check took about ninety seconds and told you everything that matters about one application: which permissions it holds, whether they're application-level or delegated, and whether the publisher's identity has been verified. The problem is scale. A mid-sized tenant commonly accumulates 150 to 400-plus enterprise application registrations over a few years — every SaaS trial, every "sign in with Microsoft" a user clicked through, every integration a departed employee set up and never documented. Manually opening each one, checking its Permissions tab, and cross-referencing whether each listed permission is genuinely dangerous is not a task a human does quarterly by hand. That's precisely why almost nobody does it at all — and precisely what the script in the next section exists to fix: the same ninety-second check, run at machine speed, across every enterprise application in the tenant, in one pass.

The fix — Get-RiskyEnterpriseAppGrants.ps1

Get-RiskyEnterpriseAppGrants.ps1 uses the Microsoft Graph PowerShell SDK to do exactly what the manual check above does, but across every enterprise application in the tenant instead of one. At a high level:

Download the script — GitHub

The script is free and open source. Download it from the Imran76Awan/Daily-Tasks repository on GitHub — no sign-in required.

Get-RiskyEnterpriseAppGrants.ps1 View full repo →

Here's the core of the scoring logic — resolving the permission catalog to GUIDs dynamically, then deciding RED, AMBER, or GREEN for each service principal:

Get-RiskyEnterpriseAppGrants.ps1 — core scoring logic
# Resolve high-risk permission NAMES to GUIDs dynamically from the tenant's own Graph SP object,
# instead of hardcoding GUIDs that could drift between environments or SDK versions
$graphSp = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'" `
    -Property Id,AppId,AppRoles,Oauth2PermissionScopes

$appRoleLookup = @{}
foreach ($permName in $script:HighRiskPermissions.Keys) {
    $role = $graphSp.AppRoles | Where-Object { $_.Value -eq $permName }
    if ($role) { $appRoleLookup[$role.Id.ToString()] = $permName }
}

# ...for each enterprise application, cross-reference its granted app roles against the lookup...
$isVerified = ($null -ne $sp.VerifiedPublisher) -and `
    (-not [string]::IsNullOrWhiteSpace($sp.VerifiedPublisher.DisplayName))

# RED needs BOTH a high-risk permission AND an unverified publisher; AMBER needs the permission
# but publisher IS verified; GREEN means no high-risk permission was found at all
$severity = if ($uniquePermissions.Count -eq 0) { 'GREEN' }
    elseif (-not $isVerified) { 'RED' }
    else { 'AMBER' }

And here's a realistic run against a fictional tenant, mirroring the Reddit scenario: one unverified AI ITSM platform holding two high-risk application permissions, one verified backup vendor holding a single high-risk delegated permission, and 212 other enterprise applications that hold nothing on the high-risk list at all.

PowerShell 7 — initial audit run
PS C:\Scripts> .\Get-RiskyEnterpriseAppGrants.ps1

[INFO] Connecting to Microsoft Graph...

=== Enterprise App / OAuth Consent Risk Audit ===
Tenant : contoso.onmicrosoft.com
Account: ██████████@contoso.com

[INFO] Resolving Microsoft Graph service principal and permission catalog...
[INFO] Resolved 8 application-permission GUIDs and 3 delegated-scope GUIDs from the high-risk catalog

[INFO] Enumerating enterprise applications (service principals)... this can take a few minutes in large tenants.
[INFO] Found 241 total enterprise applications, 214 after excluding first-party Microsoft apps

=== Findings ===

[RED  ] AI ITSM Platform                 Publisher: Not verified          Directory.ReadWrite.All; DeviceManagementApps.ReadWrite.All
[AMBER] CloudVault Backup Connector      Publisher: CloudVault Inc.       Mail.ReadWrite (delegated, AllPrincipals)

--- Summary ---
Total enterprise applications scanned : 214
RED   (high-risk perms, unverified)    : 1
AMBER (high-risk perms, verified)      : 1
GREEN (no high-risk perms found)       : 212

[INFO] Audit complete.

Remediation — turning findings into action

  1. Pull the full CSV export (-ExportCsv) and sort by Severity. Start with every RED row — an unverified publisher combined with a high-risk permission is the exact combination that matches the Reddit thread's scenario
  2. For each RED or AMBER finding, identify the business owner of that integration and confirm what the app is actually used for today. Cross-reference against the vendor's currently published minimum permission requirements — it's common to find an app still holding permissions from a feature that was never enabled, or was quietly deprecated, years after the fact
  3. Where a permission genuinely isn't needed, revoke it via Enterprise applications › [app] › Permissions › Review permissions in the portal, or programmatically with Remove-MgServicePrincipalAppRoleAssignment for an application permission (reference syntax is included as a comment at the bottom of the script)
  4. Tighten the tenant's default posture going forward: set Entra ID › Enterprise applications › Consent and permissions › User consent settings to Do not allow user consent, so every future app grant — however low-risk it looks on paper — requires an admin to actually look at it first
  5. Put this script on a recurring cadence rather than treating it as a one-off cleanup. Quarterly is a reasonable starting point for most organisations; run it more often if you onboard SaaS vendors frequently, or wire it into a scheduled task that emails the RED and AMBER rows to your security team automatically
📋 Note: There is no Group Policy or Intune CSP equivalent for this control. OAuth consent and enterprise application permissions are an Entra ID / Microsoft Graph tenant-level construct — they are not enforced on the Windows device, so there is nothing to configure through Administrative Templates or an OMA-URI. The only place this is managed is the Entra ID admin centre (or the equivalent Microsoft Graph API calls), which is exactly why the PowerShell audit above is the practical tool here rather than a device-level policy.
✅ Tip: Connect with read-only scopes (Application.Read.All, Directory.Read.All) for the audit itself, and only reconnect with Application.ReadWrite.All in a separate, deliberate session when you're actually ready to remove a specific grant. Keeping the audit and the remediation as two separate Graph sessions means a scheduled, unattended run of this script can never accidentally modify anything.

Proof it worked — the re-run after remediation

After confirming with the ITSM vendor's account team that their AI assistant module only actually needs read access to device compliance state — not write access to app deployment or directory objects — the admin in this scenario revoked Directory.ReadWrite.All and DeviceManagementApps.ReadWrite.All from the app's enterprise application object, leaving only the minimum delegated sign-in permission it needs to function. Re-running the exact same script confirms the change took effect immediately — permission grants are read live from Microsoft Graph on every run, so there is no cache to worry about.

PowerShell 7 — re-run after remediation
PS C:\Scripts> .\Get-RiskyEnterpriseAppGrants.ps1 -ShowAllFindings

[INFO] Connecting to Microsoft Graph...

=== Enterprise App / OAuth Consent Risk Audit ===
Tenant : contoso.onmicrosoft.com
Account: ██████████@contoso.com

[INFO] Resolving Microsoft Graph service principal and permission catalog...
[INFO] Resolved 8 application-permission GUIDs and 3 delegated-scope GUIDs from the high-risk catalog

[INFO] Enumerating enterprise applications (service principals)... this can take a few minutes in large tenants.
[INFO] Found 241 total enterprise applications, 214 after excluding first-party Microsoft apps

=== Findings ===

[GREEN] AI ITSM Platform                 Publisher: Not verified          (none above threshold)
[AMBER] CloudVault Backup Connector      Publisher: CloudVault Inc.       Mail.ReadWrite (delegated, AllPrincipals)
[GREEN] Zoom for Intune                  Publisher: Zoom Video Comm.      (none above threshold)
[GREEN] Adobe Acrobat Sign               Publisher: Adobe Inc.           (none above threshold)

--- Summary ---
Total enterprise applications scanned : 214
RED   (high-risk perms, unverified)    : 0
AMBER (high-risk perms, verified)      : 1
GREEN (no high-risk perms found)       : 213

[INFO] Audit complete.

The AI ITSM Platform's publisher status hasn't changed — Microsoft still hasn't verified their identity, and that's worth continuing to track separately — but it no longer holds anything on the high-risk permission list, so it now scores GREEN. The remaining AMBER finding, the backup vendor holding Mail.ReadWrite, is a genuine, ongoing decision for its app owner to justify at the next quarterly review, not a bug in the script. That is the intended end state: not a tenant with zero enterprise app permissions, but a tenant where every RED and AMBER finding has a name attached to it and a documented reason for existing.

Which enterprise app in your tenant would fail this audit right now? Most admins have never actually checked — run the script, or at minimum open your five oldest enterprise application registrations in the portal today, and see what you find.

💼 Need this done for you?
Want a proper OAuth consent risk review?

I'll audit every enterprise app in your tenant, flag the risky ones, and help you tighten consent policies without breaking integrations your business depends on.

💬 See how I can help → 📅 Book a free call

References

Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Security
Is Your LAPS Password Actually Rotating — Or Just Configured?…
Windows LAPS can look compliant in Intune and still have a local admin password that…
Entra ID
How Many of Your Global Admins Are PERMANENTLY Global Admins?…
Standing privileged access is the top finding in every security review — and turning on…
Entra ID
Do You Know Which Users Have ZERO Conditional Access Policy…
Conditional Access targets groups and apps, not "all users" by default. Gaps open…