Under attack? Get incident response help

Identity and access

Auditing OAuth app consent grants in Microsoft Entra ID

List what your Microsoft 365 users have approved, revoke risky grants, and set consent policy and an admin consent workflow in Entra ID.

Also in:TürkçeDeutschFrançaisEspañolItalianoPolskiNederlandsEesti

Illustration: Auditing OAuth app consent grants in Microsoft Entra ID

In a default Microsoft Entra ID tenant, any user can approve a third-party app that reads their mailbox, and nobody in IT is asked. If you have never reviewed this setting, assume some grants already exist and audit them before you change the policy.

What the default allows

A user can consent to an app reading their own mailbox. They cannot give an app unfettered read and write access to all files in the organisation, because that needs an administrator. Microsoft recommends allowing user consent only for apps from a verified publisher, to reduce the risk of malicious apps tricking users into granting access.

A grant is also not a password. Under OAuth 2.0 (RFC 6749) the app receives an access token with a defined scope and lifetime, issued instead of the user's credentials. The grant is its own object, and you have to find and remove it.

List what has been granted

You need at least the Cloud Application Administrator or Application Administrator role. In the Microsoft Entra admin center, go to Entra ID > Enterprise apps > All applications, select the app and open Permissions. The Admin consent tab shows permissions granted for the whole organisation. The User consent tab shows what specific users or groups granted.

The portal works app by app, so a tenant-wide view needs a loop. The Graph endpoints in the Microsoft revocation guidance are scoped to one service principal each: oauth2PermissionGrants returns delegated permissions and appRoleAssignments returns application permissions. The script below uses the equivalent cmdlets and resolves IDs to names, including application roles such as Mail.Read:

Connect-MgGraph -Scopes "Application.ReadWrite.All","DelegatedPermissionGrant.ReadWrite.All","AppRoleAssignment.ReadWrite.All"

$sps  = Get-MgServicePrincipal -All
$name = @{}
$role = @{}
foreach ($s in $sps) {
  $name[$s.Id] = $s.DisplayName
  foreach ($r in $s.AppRoles) { $role["$($s.Id)|$($r.Id)"] = $r.Value }
}

$rows = @()
foreach ($g in Get-MgOauth2PermissionGrant -All) {
  $rows += [pscustomobject]@{ App=$name[$g.ClientId]; Type="Delegated"
    Resource=$name[$g.ResourceId]; Detail=$g.Scope }
}
foreach ($sp in $sps) {
  $assigned = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.Id -All |
    Where-Object { $_.PrincipalType -eq "ServicePrincipal" }
  foreach ($a in $assigned) {
    $rows += [pscustomobject]@{ App=$sp.DisplayName; Type="Application"
      Resource=$name[$a.ResourceId]; Detail=$role["$($a.ResourceId)|$($a.AppRoleId)"] }
  }
}
$rows | Export-Csv consent-audit.csv -NoTypeInformation

These scopes come from Microsoft's revocation examples and include write access, which a read-only audit does not need. Request narrower scopes if your tenant allows it, and test the script on a small set first.

Triage order

This order is ours, not Microsoft guidance. Start with delegated grants whose scopes read or send mail or read files. Filter the Detail column for Mail and Files. Then take every application permission.

A malicious grant looks ordinary in the portal, with a plausible name and a few scopes. Several users consenting to the same unfamiliar app, from a publisher you cannot verify, is the pattern to look for. If you find one, treat it as an incident and involve our incident response team or your own.

Remove risky grants

For permissions granted by admins, open the Admin consent tab, select the ... control beside the permission and choose Revoke permission. You cannot revoke anything on the User consent tab in the portal. For those you need Graph or PowerShell.

In Graph, delete a delegated grant by its ID, or remove an application permission by its assignment ID:

DELETE https://graph.microsoft.com/v1.0/oAuth2PermissionGrants/{id}
DELETE https://graph.microsoft.com/v1.0/servicePrincipals/{resource-servicePrincipal-id}/appRoleAssignedTo/{appRoleAssignment-id}

The revocation page also has PowerShell scripts that remove all delegated and application permissions of one app. Read them before running them, because they strip everything for that service principal.

Revoking does not stop a user approving the same app again. Microsoft names two remedies: stop the app requesting the permissions through dynamic consent, or block user consent altogether. For third-party apps you cannot change what they request, so in our view blocking is the control you own.

You need the Privileged Role Administrator role. The Global Administrator role is only required if you use the admin center, where the setting is under Identity > Applications > Enterprise apps > Consent and permissions > User consent settings.

Entra ships two built-in policies for this:

IDEffect
microsoft-user-default-lowUsers consent only to apps from verified publishers or registered in your tenant, and only for permissions you classify as low impact
microsoft-user-default-legacyUsers consent to any permission that does not need admin consent, for any application

The low policy depends on you classifying permissions, which is how you select what users may approve. Do that first, then test with an ordinary user account.

Before you change anything in PowerShell or Graph, retrieve the current authorizationPolicy. Your tenant may have ManagePermissionGrantsForOwnedResource.* policies assigned, such as the one that lets developers manage consent for apps they own. Keep them in the collection or you will remove them. Disabling user consent with Graph PowerShell looks like this:

Connect-MgGraph -Scopes "Policy.ReadWrite.Authorization"

$body = @{
  "permissionGrantPolicyIdsAssignedToDefaultUserRole" = @(
    "managePermissionGrantsForOwnedResource.{other-current-policies}"
  )
}
Update-MgPolicyAuthorizationPolicy -BodyParameter $body

To allow consent under the low-impact policy instead, add managePermissionGrantsForSelf.microsoft-user-default-low to the Graph PATCH of defaultUserRolePermissions.permissionGrantPoliciesAssigned. A policy change only affects future consent, so existing grants stay in place until you remove them.

Give users a way to ask

If you block consent with no alternative, users will look for workarounds. The admin consent workflow lets them request approval instead. A Global Administrator turns it on under Entra ID > Enterprise apps > Consent and permissions > Admin consent settings. Set "Users can request admin consent to apps they are unable to consent to" to Yes, then choose:

  • Reviewers: users, groups or roles. Being a reviewer does not raise their privileges, so each must already hold the permissions to grant consent for the requested app. Only Global Administrators can approve apps requesting Microsoft Graph app roles (application permissions).
  • Email notifications: if you disable them for reviewers, requester notifications are disabled too.
  • Request lifetime and expiration reminders: the lifetime is the number of days a request stays valid. The first reminder arrives at roughly the midpoint, so day two for a three-day request.

Save, then allow up to an hour for the workflow to take effect. A removed reviewer keeps access to requests made while they held the role. New reviewers cannot act on requests created before they were added.

Entra built-in roles, Exchange RBAC and Teams resource-specific consent can also grant access, so include them in a wider review.

Where to start

  1. Run the inventory script and review delegated grants and application permissions as separate lists. Mark the apps nobody can justify.
  2. Revoke the risky grants: admin-consented ones in the portal, user-consented ones through Graph or PowerShell.
  3. Read the current authorizationPolicy, then set user consent to microsoft-user-default-low with classified permissions, or disable it, keeping the ManagePermissionGrantsForOwnedResource.* entries.
  4. Enable the admin consent workflow. Name reviewers whose roles can grant consent for what users will ask for, and keep a Global Administrator among them, because only that role approves Microsoft Graph application permissions.
  5. Repeat the review on a schedule. If you lack the time, our consulting team can run it as an assessment, and our managed security service can cover monitoring.

How we can help

Consulting and training

We assess where you stand, set priorities with you and train your staff to recognise attacks.

Contact us
AngelForce team

Written by the AngelForce team: security consultants with CEH, LPT Master and CISA certifications who test, monitor and defend systems for organisations across Europe.

Written with AI assistance from public sources listed below, and reviewed by the AngelForce team before publication.

Sources

  1. learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-user-consent
  2. learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-admin-consent-workflow
  3. learn.microsoft.com/en-us/entra/identity/enterprise-apps/manage-application-permissions
  4. www.rfc-editor.org/rfc/rfc6749.html

Articles about Identity and access

Tell us what you need to protect

Describe your environment and what you want to achieve. We will reply by email.

Contact us
info@angelforce.eu +372 5705 2044

AngelForce OÜ · Tallinn, Estonia