Skip to content

Authorization_RequestDenied: insufficient privileges on Microsoft Graph

Short answer: Authorization_RequestDenied means the directory refused the request because the caller does not have enough privilege. The message is always the same seven words and names nothing, so the useful information is which endpoint you called and whether your caller is an app or a user. It also appears on reads, where it hides whether the object exists.

Fix: Work out the permission the endpoint needs from Microsoft's permissions reference, add it to the app registration or the user's role, and grant admin consent. For an app-only token, check you added an Application permission and not a Delegated one. Then acquire a new token; an old one does not carry the new role. Full steps

At a glance
Error codeAuthorization_RequestDenied
HTTP status403
CategoryGraph permissions
Attack signalMedium: worth a look in context

What does Authorization_RequestDenied mean?

Section titled “What does Authorization_RequestDenied mean?”

The directory refused the operation because the caller does not have enough privilege for it. HTTP 403, and the message is one fixed sentence:

Insufficient privileges to complete the operation.

Microsoft’s troubleshooting article for this code quotes the same string — “Authorization_RequestDenied. Insufficient privileges to complete the operation.” — and says “This error typically occurs because the user or app doesn’t have sufficient permissions.”

The retired Azure AD Graph catalogue, which is the only other Microsoft page that defines the code, gives a different message for it: “The specified credentials do not have sufficient privileges to make this request.” That wording no longer matches what the service returns; the sentence above is what a lab tenant got on 31 October 2026. The catalogue’s description of the cause is still accurate: “The request is denied due to insufficient privileges. For example, a non-administrative principal does not have permission to delete a resource.”

This is one of three 403 codes Graph uses for permission failures, and it is the least informative of the three:

Code What the message gives you
Authentication_MSGraphPermissionMissing Names the permission you need
AccessDenied “required scopes are missing in the token”
Authorization_RequestDenied “Insufficient privileges to complete the operation.”

On 31 October 2026 an automated run used an app-only token whose roles claim, recorded by the run, held Application.ReadWrite.OwnedBy and User.ReadWrite.All and nothing else. These requests returned this code:

Request HTTP Message
POST /groups (create a group) 403 Insufficient privileges to complete the operation.
GET /groups/<unused GUID> 403 Insufficient privileges to complete the operation.
GET /directoryRoles/<unused GUID> 403 Insufficient privileges to complete the operation.
GET /devices/<unused GUID> 403 Insufficient privileges to complete the operation.
GET /contacts/<unused GUID> 403 Insufficient privileges to complete the operation.
GET /directory/administrativeUnits/<unused GUID> 403 Insufficient privileges to complete the operation.
GET /groups?$top=1 and GET /devices?$top=1 403 Insufficient privileges to complete the operation.

The write is the expected case. The reads are the interesting ones, because the GUID in each belonged to no object at all, and a collection the app cannot read answers for an object that does not exist exactly as it answers for one that does.

A 403 on a single-object GET tells you nothing about whether the object exists. The same request shape against collections the app could read returned 404 Request_ResourceNotFound for an equally non-existent GUID, and the run read each collection as a control:

Collection GET /<collection>?$top=1 GET /<collection>/<unused GUID>
users 200 404 Request_ResourceNotFound
applications 200 404 Request_ResourceNotFound
servicePrincipals 200 404 Request_ResourceNotFound
groups 403 Authorization_RequestDenied 403 Authorization_RequestDenied
devices 403 Authorization_RequestDenied 403 Authorization_RequestDenied
directoryRoles not read 403 Authorization_RequestDenied
directory/administrativeUnits not read 403 Authorization_RequestDenied
contacts not read 403 Authorization_RequestDenied

The correlation is exact across all five collections where both levels were tested: every one the app could read answered a GUID belonging to nothing with 404, and every one it could not read answered the same thing with 403. The three marked “not read” were only probed with a GUID.

So read a 403 as “I cannot see into this collection” and not as “this object is gone”. Our reading is that type-level permission is checked before the object is looked up; what the run establishes is the correlation.

Medium, in aggregate, for the reason the table above shows: the 403-versus-404 split turns Graph into a permission oracle.

An identity that walks single-object GETs across /users, /groups, /applications, /servicePrincipals, /devices, /contacts and /directoryRoles with made-up GUIDs learns exactly which collections it can read, purely from the status codes, without ever reading an object or triggering anything that looks like data access. In the lab the mapping held in both directions for every collection where both levels were tested — five of them. That is a cheap, quiet way to map what a compromised app registration or service principal is good for before using it.

A single occurrence is noise — nearly always an integration whose consent was never granted, or an app-only token sent to an endpoint that only supports delegated access. What is worth alerting on is one service principal producing 403s across several different resource types in a short window.

These failures do not appear in Entra sign-in logs. The token acquisition that preceded them does, in AADServicePrincipalSignInLogs, and it succeeded, so it looks ordinary. The calls land in MicrosoftGraphActivityLogs: KQL for the probe pattern, including a query for the 403-and-404 object-lookup shape described above.

  1. Identify the permission the endpoint needs. The message will not tell you, so look the operation up in Microsoft’s permissions reference, which lists them per endpoint with the least-privileged option first. For POST /groups it is Group.ReadWrite.All; for reading groups, Group.Read.All or GroupMember.Read.All.
  2. Check the permission type matches the token. An app-only token (client credentials) needs an Application permission. A token acquired for a signed-in user needs a Delegated permission. Adding one when you needed the other is the commonest reason the error survives a fix, because the admin-consent screen looks identical either way.
  3. Grant admin consent. In the Microsoft Entra admin center: Identity > Applications > App registrations > your app > API permissions > Grant admin consent for <tenant>. Application permissions do nothing before this.
  4. Acquire a new token. Permissions travel inside the token as roles. A token issued before the consent does not contain the new role and will keep failing until it expires. Clear the token cache or restart the process.
  5. If the caller is a user, the permission may not be the problem. Some directory operations also require a directory role regardless of Graph permissions — deleting a user, or editing a role assignment, needs an administrator. A delegated token can only ever do what both the permission and the signed-in user’s role allow.
  6. For writes against objects your app created, check scope. Application.ReadWrite.OwnedBy is deliberately narrower than Application.ReadWrite.All: it covers only applications the app itself owns. An operation on an object it does not own returns this code even though the permission looks present.

Sources

  1. Troubleshoot Authorization_RequestDenied error with Microsoft Graph
  2. Azure AD Graph error codes and error handling (retired)
  3. Microsoft Graph permissions reference
  4. Microsoft Graph error responses and resource types