Microsoft Graph cannot return a complete Owner/Member/Visitor access report; use Graph to discover site collections, then query each site with SharePoint REST or CSOM using certificate-based app-only authentication.
Why the Graph permissions endpoint does not work
GET /sites/{siteId}/permissions lists permissions granted to applications on a site, not the site’s user and group role assignments. It also does not support retrieving subsite permissions ^1^.
SharePoint access is represented by role assignments that connect:
- A principal: user, SharePoint group, or directory group
- A role definition: Full Control, Edit, Contribute, Read, Limited Access, or a custom level
- A scope: web, list, folder, or item
Owners, Members, and Visitors are only the default SharePoint groups; custom groups and direct assignments are also possible ^2^.
Recommended app-only implementation
In addition to your Microsoft Graph permissions, add this SharePoint API application permission to the app registration:
Grant tenant-wide admin consent. For SharePoint REST/CSOM app-only authentication, configure an X.509 certificate; Microsoft’s SharePoint guidance requires certificate authentication for this Entra app-only model ^3^.
This is a highly privileged permission. If the report covers only selected sites, use Sites.Selected and explicitly grant the application access to each target site instead ^4^.
Acquire two separate tokens:
- Graph discovery/group expansion:
https://graph.microsoft.com/.default
- SharePoint REST/CSOM:
https://{tenant}.sharepoint.com/.default
The SharePoint token must be requested using the certificate, not the Graph access token ^3^.
2. Enumerate site collections with Graph
Use:
GET https://graph.microsoft.com/v1.0/sites/getAllSites
Authorization: Bearer {graph-token}
This supports application authentication with Sites.Read.All as the least-privileged Graph permission. Continue requesting every @odata.nextLink until it is absent ^5^.
If OneDrive personal sites are not part of the report, exclude results where isPersonalSite is true. Site-collection discovery alone does not enumerate every subsite/web.
3. Read each web’s role assignments with SharePoint REST
For every site or subsite URL, send the SharePoint token to:
GET https://{tenant}.sharepoint.com/sites/{site}/_api/web/roleassignments
?$expand=Member,RoleDefinitionBindings
&$select=Member/Id,Member/Title,Member/LoginName,Member/Email,
Member/PrincipalType,RoleDefinitionBindings/Id,
RoleDefinitionBindings/Name
Accept: application/json;odata=nometadata
Authorization: Bearer {sharepoint-token}
The SharePoint API exposes web role assignments through /_api/web/roleassignments ^6^.
For each result:
-
Member identifies the assigned user or group.
-
RoleDefinitionBindings supplies permission levels such as Full Control, Edit, Contribute, Read, or custom roles.
- Do not treat an assignment containing only Limited Access as meaningful site access; it commonly indicates access to a lower-level secured object, which must be inspected separately.
4. Expand group principals
For a SharePoint group, use its SharePoint Member/Id:
GET https://{site-url}/_api/web/sitegroups({group-id})/users
Accept: application/json;odata=nometadata
Authorization: Bearer {sharepoint-token}
SharePoint groups and their users are site-collection-scoped; CSOM also exposes them through SiteGroups and Group.Users ^7^.
For a Microsoft Entra or Microsoft 365 group, first map the SharePoint claim in Member/LoginName to the group’s Entra directory object ID. The SharePoint principal ID is not the Entra group ID. Then call:
GET https://graph.microsoft.com/v1.0/groups/{entra-group-id}/members
Follow @odata.nextLink, and recursively process nested groups when the report requires transitive membership. The application needs GroupMember.Read.All; add User.ReadBasic.All to return basic user properties rather than only IDs and object types ^8^.
Reporting limitations
A web-level role-assignment report is not a complete effective-access calculation. For exhaustive results, also inspect:
- Subsites and webs
- Lists, folders, and items with unique permissions
- Direct assignments and custom SharePoint groups
- Site collection administrators
- Sharing links and broad principals such as “Everyone except external users”
- Nested directory groups
SharePoint objects inherit permissions by default but can break inheritance and define their own role assignments ^9^. Tenant-wide item-level enumeration can therefore be expensive.
Member/Email can also be empty or outdated for guests and groups. Where an authoritative address is required, resolve the user through Graph using the mapped Entra object ID or login identity and report mail, falling back to userPrincipalName according to your reporting policy.
References
- List permissions
- Authorization, users, groups, and the object model in SharePoint
- Granting access via Entra ID Application Permissions
- Understanding Resource Specific Consent for Microsoft Graph and SharePoint Online
- sites: getAllSites
- SharePoint .NET Server, CSOM, JSOM, and REST API index
- Adds a user to a specified SharePoint role (e.g., 'Read') using the SharePoint .NET Framework client object model (CSOM).
- Overview of Microsoft Graph permissions
- Set custom permissions on a list by using the REST interface