DEV Community

AdminPackStudio
AdminPackStudio

Posted on

Connect-MgGraph "Insufficient privileges to complete the operation" - scopes, roles, consent, and app-only, fixed in order

Connect-MgGraph "Insufficient privileges": fixed in order

You connect, run a cmdlet, and get something like this:

Get-MgUser_List: Insufficient privileges to complete the operation.
Status: 403 (Forbidden)
ErrorCode: Authorization_RequestDenied
Enter fullscreen mode Exit fullscreen mode

The error means: the token you're holding doesn't allow this call. It doesn't tell you why. In practice there are six usual causes, and checking them in order is faster than adding random scopes until something works.

Everything in this post is about reading your current state and requesting the right access. Granting consent or roles is a change for whoever owns that in your tenant. Module behavior and permission names change over time, so check current Microsoft Graph docs.


1. Look at the token you actually have

Start here every time:

Get-MgContext | Select-Object Account, TenantId, AuthType, AppName, ClientId, Scopes
Enter fullscreen mode Exit fullscreen mode

What to check:

  • TenantId: is it the tenant you think it is? Multi-tenant admins hit this more than they admit.
  • AuthType: Delegated means you're acting as yourself. AppOnly means you're acting as an app with a certificate or secret. The fixes are different.
  • Scopes: the permissions in this token. If the scope your cmdlet needs isn't listed, that's the problem.
  • AppName / ClientId: for interactive sign-in without a custom app, this is usually Microsoft Graph Command Line Tools. That enterprise app is where delegated consent is recorded.

2. Find the scope the cmdlet needs

Don't guess. The SDK can tell you:

# Permissions a specific cmdlet can use
Find-MgGraphCommand -Command Get-MgUser |
  Select-Object -First 1 -ExpandProperty Permissions |
  Select-Object Name, IsAdmin, Description

# Search permissions by keyword
Find-MgGraphPermission devicemanagement -PermissionType Delegated |
  Select-Object Name, Consent, Description
Enter fullscreen mode Exit fullscreen mode

Find-MgGraphCommand lists every permission that could work, often from least to most privileged. Pick the smallest one. For reading users that's usually User.Read.All, not Directory.ReadWrite.All.

Then reconnect with it. Scopes are fixed when the token is issued, so disconnect first:

Disconnect-MgGraph
Connect-MgGraph -Scopes 'User.Read.All' -NoWelcome
(Get-MgContext).Scopes
Enter fullscreen mode Exit fullscreen mode

Watch for properties that need extra permissions. A plain Get-MgUser works with User.Read.All, but asking for signInActivity needs AuditLog.Read.All as well, and the tenant needs the right Entra ID license for sign-in activity data. The error looks the same.


3. Consent: "Need admin approval"

If adding the scope gives you a Need admin approval prompt instead of a token, the scope needs admin consent, or your tenant doesn't let users consent to apps.

The fix isn't to find a way around the prompt. Ask an admin who can grant consent (for example, a Privileged Role Administrator or Cloud Application Administrator, depending on the permission) to grant it for Microsoft Graph Command Line Tools, or better, for a dedicated app registration your team owns.

You can read what's already been granted to the command line tools app:

$sp = Get-MgServicePrincipal -Filter "appId eq '14d82eec-204b-4c2f-b7e8-296a70dab67e'"
Get-MgOauth2PermissionGrant -Filter "clientId eq '$($sp.Id)'" |
  Select-Object ConsentType, PrincipalId, Scope
Enter fullscreen mode Exit fullscreen mode

ConsentType = AllPrincipals is tenant-wide admin consent. Principal is consent for one user. (Reading grants needs a read scope that covers service principals and grants, such as Application.Read.All plus directory read access. Check Find-MgGraphPermission if it fails.)

A dedicated app registration with only the scopes your scripts need is easier to audit than one shared app that has collected every scope anyone ever asked for.


4. Delegated = scope AND role

This is the cause people miss most. With delegated permissions, you get the overlap of the token's scopes and your own Entra role.

So User.ReadWrite.All in the token doesn't let a user with no admin role update other users. The scope says "the app may do this on your behalf", and your role says "you aren't allowed to." Result: 403.

Check your roles:

$me = (Get-MgContext).Account
Get-MgUserMemberOf -UserId $me -All |
  Where-Object { $_.AdditionalProperties['@odata.type'] -eq '#microsoft.graph.directoryRole' } |
  ForEach-Object { $_.AdditionalProperties['displayName'] }
Enter fullscreen mode Exit fullscreen mode

Some operations need a specific role even with the right scope. For example, changing settings on users who hold privileged roles typically needs a higher-privileged admin role than changing settings on ordinary users. If the call works on a test user but fails on an admin account, this is why.


5. PIM: the role is eligible, not active

If your tenant uses Privileged Identity Management, you may be eligible for a role without having it active. The listing above only shows active roles.

After activating the role:

  1. Wait a minute or two.
  2. Disconnect-MgGraph, then Connect-MgGraph again.

The old token was issued before activation, and the SDK caches tokens. Reconnecting is what picks up the new role.


6. App-only: application permissions and admin consent

For unattended scripts you connect as an app:

Connect-MgGraph -ClientId '<app-id>' -TenantId '<tenant-id>' -CertificateThumbprint '<thumbprint>' -NoWelcome
(Get-MgContext).AuthType   # AppOnly
(Get-MgContext).Scopes     # application permissions in the token
Enter fullscreen mode Exit fullscreen mode

App-only has no user, so there's no role overlap. The token has exactly the application permissions that an admin consented to. Common failures:

  • The permission was added as delegated in the app registration, not application. App-only tokens ignore delegated permissions.
  • The permission was added but admin consent was never granted. The portal shows "Not granted for ".
  • Consent was granted after your session started. Reconnect.
  • Some workloads have their own access model on top of Graph. A Graph permission alone may not be enough for every Exchange or Teams operation. Check the docs for that API.

7. Getting the full error

When the short message isn't enough:

Get-MgUser -UserId 'someone@contoso.com' -Debug
Enter fullscreen mode Exit fullscreen mode

-Debug shows the request and response, including the error code and a request ID. Include that request ID if you open a support case. Don't paste tokens or full debug output into public forums. Redact tenant IDs, UPNs, and anything that looks like a token.

Also note: errors starting with AADSTS happen at sign-in, not at the Graph call. AADSTS65001 is a consent problem. AADSTS53003 means a Conditional Access policy blocked the sign-in. Those need a different fix from a 403.


8. The checklist

Check Command or place Typical fix
Right tenant, right auth type Get-MgContext Reconnect to the right tenant
Scope in the token (Get-MgContext).Scopes Reconnect with the least-privilege scope
Which scope is needed Find-MgGraphCommand, Find-MgGraphPermission Pick the smallest one listed
Consent granted Enterprise app permissions, Get-MgOauth2PermissionGrant Ask the consent owner
Your role allows it (delegated) Get-MgUserMemberOf Request the right role
PIM role active PIM portal Activate, then reconnect
App permission type and consent (app-only) App registration > API permissions Application type + admin consent

Want a read-only Graph setup that avoids most of this?

The Microsoft Graph Read-Only Inventory Toolkit ($24) from Admin Pack Studio includes a least-privilege, read-only app registration checklist with a starter scope table and consent evidence, scheduling options with a secrets hygiene checklist, and troubleshooting cards. It also ships three read-only Graph PowerShell scripts: an Entra device inventory, a user and assigned-license inventory, and a Conditional Access policy summary. The scripts only read and export to CSV.

Get the toolkit: https://cashflow4375.gumroad.com/l/microsoft-graph-read-only-inventory-toolkit?utm_source=devto&utm_medium=article&utm_campaign=mggraph_403

Hitting AADSTS53003 instead? That's Conditional Access. The Entra ID Conditional Access Starter Pack covers report-only rollout, exclusions, and break-glass patterns: https://cashflow4375.gumroad.com/l/nhuyrc


Admin Pack Studio. Not affiliated with Microsoft. Microsoft Graph, Microsoft Entra ID, and Privileged Identity Management are Microsoft products. Operational guidance for admins authorized to manage their tenant. Permission names, role requirements, and SDK behavior change, so check current Microsoft documentation. Examples use placeholder names.

Top comments (0)