Product/Service: Microsoft Graph API — Reports / Admin Reports Settings
Affected endpoint: PATCH https://graph.microsoft.com/{beta|v1.0}/admin/reportSettings
Permission model: Delegated, via Granular Delegated Admin Privileges (GDAP)
Summary:
We are a Microsoft CSP partner managing customer tenants via GDAP. Our multi-tenant application holds the delegated ReportSettings.ReadWrite.All permission with admin consent. Per Microsoft's own documentation (Authorization for APIs to read Microsoft 365 usage reports: https://learn.microsoft.com/en-us/graph/reportroot-authorization, referenced directly from the adminReportSettings: update API reference: https://learn.microsoft.com/en-us/graph/api/adminreportsettings-update), a delegated caller should be authorized for this endpoint if the identity holds any one of: Global Administrator, Exchange Administrator, SharePoint Administrator, Teams Administrator, Teams Communications Administrator, Global Reader, Usage Summary Reports Reader, or Reports Reader.
In practice, calls from a GDAP-derived identity holding Global Reader and Reports Reader simultaneously (in addition to Exchange/SharePoint/Teams/Intune/Security Administrator) are rejected with 403 S2SUnauthorized. The call only succeeds once Global Administrator is additionally granted via the GDAP relationship — a role well outside the documented "least privileged" set for this operation, and one that runs counter to the entire purpose of GDAP's least-privilege model.
Steps to reproduce:
1. Establish a GDAP relationship between our CSP tenant and a customer tenant, granting (at minimum) Exchange Administrator, SharePoint Administrator, Teams Administrator, Security Administrator, Intune Administrator, Global Reader, and Reports Reader — explicitly not Global Administrator.
2. Obtain a delegated access token scoped to the customer tenant via the GDAP token-exchange flow (grant_type=refresh_token, scope=https://graph.microsoft.com/.default), using the multi-tenant app's consented ReportSettings.ReadWrite.All delegated permission.
3. Call:
PATCH https://graph.microsoft.com/beta/admin/reportSettings
Content-Type: application/json
{ "displayConcealedNames": false }
4. Observe the response.
Actual result:
{
"error": {
"code": "UnknownError",
"message": "{\"error\":{\"code\":\"S2SUnauthorized\",\"message\":\"Invalid permission.\"}}",
"innerError": {
"date": "2026-07-27T19:08:03",
"request-id": "8cd946ec-2f8b-44cf-9deb-c7008e40daef",
"client-request-id": "8cd946ec-2f8b-44cf-9deb-c7008e40daef"
}
}
}
Expected result:
A 204 No Content response, per the documented permission model — since the calling identity holds Global Reader and/or Reports Reader, both explicitly listed as sufficient least-privileged roles for this exact operation.
Confirmed via direct testing:
- Decoded the access token's wids claim and verified it contains Global Reader (f2ef992c-3afb-46b9-b7cf-a126ee74c451) and Reports Reader (4a5d8f65-41da-4de4-8968-e035b65339cf), alongside Exchange Administrator, SharePoint Administrator, and Teams Administrator — still rejected.
- Repeated the test with only SharePoint Administrator, Teams Administrator, Security Administrator, and Intune Administrator granted — same S2SUnauthorized rejection.
- Added Global Administrator to the same GDAP relationship and retried — the identical request succeeded with 204 No Content.
This indicates the backend authorization check for this endpoint does not honor GDAP-sourced role claims for any role other than Global Administrator, despite the documented permission model listing several lower-privilege alternatives as sufficient.
Please confirm whether this is expected/by-design behavior (in which case the documentation should be corrected to state that only Global Administrator is honored for GDAP-delegated callers) or a bug in the backend authorization check for this endpoint