Skip to content
← All field notes

Field Notes · Sheet 04 / 30 · Identity and federation

Who can grant an app access to your data?

Who in your tenant can let an app read their mailbox: the three user consent settings in Entra ID, the admin consent workflow, and the grants left behind.

Bradley Baker · · 3 min read

A scale of three user consent positions from most restrictive to most open: block user consent, verified publishers with low-impact permissions only, and any app. Below, the illicit consent grant pattern: app requests Mail.Read, user accepts, tokens issued, mailbox read through the API. A box notes the admin consent workflow.
Sheet 04 / 30 · Drawn by Bradley BakerFull size

Who in your tenant can give a third-party app permission to read their mailbox? Unless someone changed it, the answer is any user. By default, Entra lets every user consent to apps for any permission that doesn't require admin consent. Letting an app read your own mailbox is one of those permissions. Letting it read every file in the organization is not.

User consent is how OAuth apps get delegated permissions without an admin involved, and it's also how illicit consent grant attacks work. A convincing app asks for Mail.Read, the user clicks Accept, Entra issues tokens, and the attacker reads mail through the API without ever learning the password. MFA doesn't help, because the user already passed it.

Even Microsoft shutting a malicious app down doesn't end its access at once. When Microsoft disables one, new token and refresh token requests are denied, but the access tokens it already holds stay valid until they expire.

Under Enterprise apps, in Consent and permissions, Entra offers three positions for user consent.

SettingWhat a user can consent toBuilt-in policy
Block user consentNothing. Every request goes to an admin.None assigned
Verified publishers, selected permissionsApps from verified publishers or registered in your tenant, for permissions you classify as low impactmicrosoft-user-default-low
Any appAny permission that doesn't require admin consentmicrosoft-user-default-legacy
The user consent settings in Microsoft Entra ID, and the built-in app consent policy behind each.

Microsoft recommends the middle setting. It's only as tight as the permission list behind it, though, because users can consent to whatever you classify as low impact.

Classifications live under Consent and permissions, Permission classifications, and only delegated permissions that don't require admin consent can be classified. Microsoft's own example classifies the four that basic sign-in needs: openid, profile, email, and offline_access. Even those four let an app read the signed-in user's profile and keep that access after the user stops using the app, which is worth knowing before you add more.

One case skips user consent entirely. An app that requires users to be assigned to it needs an administrator's consent, whatever the user consent setting says.

Whichever setting you choose, turn on the admin consent workflow. A blocked user can request the app, designated reviewers approve or deny it, and you keep a record of who asked for what. Microsoft's documentation adds the details that shape how it runs:

  • It's under Enterprise apps, Consent and permissions, Admin consent settings. Turning it on takes a Global Administrator, and it can take up to an hour to start working.
  • Reviewers see requests in the admin center and, if you turn on notifications, by email. Requests expire after the number of days you set, and reviewers can get reminders before they do.
  • Being a reviewer grants nothing. To approve, a reviewer needs the rights to grant admin consent for that app, and only a Global Administrator can approve a request for Microsoft Graph application permissions.
  • Reviewers added later can't act on requests made before they were added, and reviewers you remove still get reminders for requests made while they were on the list.

A new setting doesn't touch old grants

Changing the user consent setting only affects consent from then on. Grants users already made stay in place, with the access they gave, which is why the post ended on a question about reading the list.

In the admin center, each enterprise app's Permissions page shows organization-wide grants on the Admin consent tab and per-user grants on the User consent tab. The portal can revoke the first kind but not the second, which has to come out through Microsoft Graph or PowerShell. For a view across the whole tenant, list the delegated grants directly.

PowerShell

Connect-MgGraph -Scopes "Directory.Read.All"

# consentType Principal: one user consented for themselves
Get-MgOauth2PermissionGrant -All -Filter "consentType eq 'Principal'" |
  Select-Object ClientId, PrincipalId, Scope
Every delegated grant a user made for themselves. ClientId is the app's service principal, and Scope lists what it can do. Directory.Read.All is the least privileged permission Microsoft Graph documents for this list.

In the tenant

In the 4,300-user tenant I ran, app registrations and API permission grants went through consent policy as part of the zero standing privilege program.

So the question from the post stands: when did you last pull the list of OAuth permission grants in your tenant and read it?

Sources

  1. Configure how users consent to applicationslearn.microsoft.com
  2. Configure the admin consent workflowlearn.microsoft.com
  3. Configure permission classificationslearn.microsoft.com
  4. Review permissions granted to enterprise applicationslearn.microsoft.com
  5. Protect against consent phishinglearn.microsoft.com
  6. List oauth2PermissionGrants (Microsoft Graph)learn.microsoft.com

From the field reports

  • Entra ID
  • User consent
  • OAuth 2.0
  • Microsoft Graph
  • PowerShell
This note on LinkedIn

Recon log

Findings 0/46

0/16 behavior and secret eggs. Hardware finds depend on the machine you visit from.

Hardware details are read by your browser and stay there. When you find an egg, only its name is counted, with no identifier attached, and nothing is counted if Global Privacy Control or Do Not Track is on.

Display0/7

  • Undiscovered (not found yet)

    rare

    Hint: Visit on a very large display.

  • Undiscovered (not found yet)

    uncommon

    Hint: Some monitors are wider than others.

  • Undiscovered (not found yet)

    uncommon

    Hint: Two screens are better than one.

  • Undiscovered (not found yet)

    rare

    Hint: Turn a monitor on its side.

  • Undiscovered (not found yet)

    common

    Hint: Pixels per inch matter.

  • Undiscovered (not found yet)

    uncommon

    Hint: Faster than 60 frames a second.

  • Undiscovered (not found yet)

    common

    Hint: Colors beyond sRGB.

Hardware0/11

  • Undiscovered (not found yet)

    rare

    Hint: Bring a flagship graphics card.

  • Undiscovered (not found yet)

    legendary

    Hint: A GPU that lives in a rack.

  • Undiscovered (not found yet)

    common

    Hint: A Mac with Apple silicon.

  • Undiscovered (not found yet)

    rare

    Hint: A Windows machine built for heavy work.

  • Undiscovered (not found yet)

    rare

    Hint: A Mac built for heavy work.

  • Undiscovered (not found yet)

    rare

    Hint: Two dozen threads or more.

  • Undiscovered (not found yet)

    rare

    Hint: Windows, but not on x86.

  • Undiscovered (not found yet)

    uncommon

    Hint: The year of the Linux desktop.

  • Undiscovered (not found yet)

    uncommon

    Hint: A laptop that boots straight into a browser.

  • Undiscovered (not found yet)

    uncommon

    Hint: No graphics card at all.

  • Undiscovered (not found yet)

    common

    Hint: A laptop you can poke.

Environment0/11

  • Undiscovered (not found yet)

    uncommon

    Hint: Visit while your battery is nearly flat.

  • Undiscovered (not found yet)

    uncommon

    Hint: Your browser has a setting for saving data.

  • Undiscovered (not found yet)

    uncommon

    Hint: Visit very late at night.

  • Undiscovered (not found yet)

    common

    Hint: Visit on a day off.

  • Undiscovered (not found yet)

    uncommon

    Hint: A browser with a lion on it.

  • Undiscovered (not found yet)

    common

    Hint: A browser with a fox on it.

  • Undiscovered (not found yet)

    uncommon

    Hint: An accessibility setting that calms things down.

  • Undiscovered (not found yet)

    uncommon

    Hint: Tell websites not to track you.

  • Undiscovered (not found yet)

    rare

    Hint: Visit from the Lone Star State.

  • Undiscovered (not found yet)

    common

    Hint: A newer version of HTTP.

  • Undiscovered (not found yet)

    rare

    Hint: A very narrow window.

Behavior0/7

  • Undiscovered (not found yet)

    uncommon

    Hint: Drag the edge of your browser window around.

  • Undiscovered (not found yet)

    uncommon

    Hint: Reach the bottom of the page quickly.

  • Undiscovered (not found yet)

    uncommon

    Hint: Try printing this page.

  • Undiscovered (not found yet)

    common

    Hint: Toggle the theme a few times.

  • Undiscovered (not found yet)

    rare

    Hint: Lose your connection.

  • Undiscovered (not found yet)

    rare

    Hint: Plug in a controller and press a button.

  • Undiscovered (not found yet)

    uncommon

    Hint: Sign the guestbook.

Secrets0/10

  • Undiscovered (not found yet)

    rare

    Hint: A famous cheat code.

  • Undiscovered (not found yet)

    common

    Hint: There's a terminal in here somewhere.

  • Undiscovered (not found yet)

    uncommon

    Hint: Ask the terminal about your machine.

  • Undiscovered (not found yet)

    uncommon

    Hint: Ask the terminal for root.

  • Undiscovered (not found yet)

    rare

    Hint: sudo, but make it a job offer.

  • Undiscovered (not found yet)

    rare

    Hint: The most dangerous command there is.

  • Undiscovered (not found yet)

    legendary

    Hint: Open your browser's developer console.

  • Undiscovered (not found yet)

    uncommon

    Hint: Click the logo. Then keep clicking.

  • Undiscovered (not found yet)

    legendary

    Hint: Type the 82nd's favorite word anywhere on the page.

  • Undiscovered (not found yet)

    legendary

    Hint: Find every egg that doesn't depend on your hardware.

Finds are saved in this browser only.

guest@bradbaker-it.com:~