Introduction
Microsoft 365 does not provide a built-in report to extract complete permission details across SharePoint (site, libraries, folders, files, and items) in a single view.
To achieve this, a custom PnP PowerShell script is used to generate a detailed permission report.
Purpose
This solution helps to:
- Identify who has access to what
- Detect unique permissions (broken inheritance)
- Expand SharePoint group members into individual users
- Support security audits and access reviews
When This is Required
Use this approach when:
- Performing security or audit reviews
- Investigating unauthorized access
- Validating data access across files/folders
- Preparing compliance reports
What the Report Includes
- Site, Library, Folder, File, and Item-level permissions
- User details (Name, UPN, Email)
- Permission levels (Read, Contribute, Full Control)
- Direct vs Group-based access
Prerequisites
1. Required PowerShell Modules
Install the PnP PowerShell module:
PowerShell
Install-Module -Name PnP.PowerShell -Scope CurrentUser
Show more lines
Verify installation:
PowerShell
Get-Module PnP.PowerShell -ListAvailable
Show more lines
2. Required Permissions (Very Important)
To successfully extract full permission details, the account must have:
Recommended
- Site Collection Administrator (Best option)
Minimum Required
- Full Control on the target SharePoint site
- Ability to:
- Read permissions
- Access all lists and libraries
- View items (including restricted content)
3. Admin Role Requirements
Depending on scope:
For Single Site Reports
- Site Collection Admin is sufficient
For Multiple Sites / Tenant-Level Execution
- SharePoint Administrator role required
4. Authentication Method
Use modern authentication:
PowerShell
Connect-PnPOnline -Url “<SiteURL>” -Interactive
Show more lines
5. Environment Requirements
- Windows machine or server
- PowerShell 5.1 or PowerShell 7+
- Internet access to Microsoft 365
6. Access Considerations
- Script will only return data based on access level
- If permissions are missing:
- Some users/groups may not appear
- Some items may be skipped
PowerShell Script
Update the $SiteURL before running
# Create Output Folder
New-Item -ItemType Directory -Force -Path “C:\Temp”
# Site URL
$SiteURL = “https://yourtenant.sharepoint.com/sites/yoursite”
# Output File
$ReportOutput = “C:\Temp\SharePoint_Permission_Report.csv”
# Connect to SharePoint
Connect-PnPOnline -Url $SiteURL -Interactive
# Report Array
$PermissionData = New-Object System.Collections.ArrayList
Function Get-PermissionDetails {
param ($Object, $ObjectType, $ObjectTitle, $ObjectURL)
Get-PnPProperty -ClientObject $Object -Property HasUniqueRoleAssignments, RoleAssignments
if (-not $Object.HasUniqueRoleAssignments) { return }
foreach ($RoleAssignment in $Object.RoleAssignments) {
Get-PnPProperty -ClientObject $RoleAssignment -Property RoleDefinitionBindings, Member
$PermissionLevels = (
$RoleAssignment.RoleDefinitionBindings |
Select-Object -ExpandProperty Name |
Where-Object { $_ -ne “Limited Access” }
) -join “, “
if ([string]::IsNullOrEmpty($PermissionLevels)) { continue }
$Member = $RoleAssignment.Member
if ($Member.PrincipalType -eq “SharePointGroup”) {
$Users = Get-PnPGroupMembers -Identity $Member.Title
foreach ($User in $Users) {
if ($User.Title -eq “System Account”) { continue }
$PermissionData.Add([PSCustomObject]@{
ObjectType = $ObjectType
ObjectTitle = $ObjectTitle
ObjectURL = $ObjectURL
GroupName = $Member.Title
UserName = $User.Title
UserUPN = $User.LoginName
Email = $User.Email
Permissions = $PermissionLevels
}) | Out-Null
}
}
else {
if ($Member.Title -ne “System Account”) {
$PermissionData.Add([PSCustomObject]@{
ObjectType = $ObjectType
ObjectTitle = $ObjectTitle
ObjectURL = $ObjectURL
GroupName = “Direct”
UserName = $Member.Title
UserUPN = $Member.LoginName
Email = $Member.Email
Permissions = $PermissionLevels
}) | Out-Null
}
}
}
}
$Web = Get-PnPWeb
# Site Level
Get-PermissionDetails $Web “Site” $Web.Title $Web.Url
# Lists & Libraries
$Lists = Get-PnPList | Where-Object { $_.Hidden -eq $false }
foreach ($List in $Lists) {
Get-PermissionDetails $List “Library” $List.Title $List.RootFolder.ServerRelativeUrl
$Items = Get-PnPListItem -List $List.Title -PageSize 500
foreach ($Item in $Items) {
if ($Item.FileSystemObjectType -eq “File”) {
Get-PermissionDetails $Item “File” $Item.FieldValues.FileLeafRef $Item.FieldValues.FileRef
}
elseif ($Item.FileSystemObjectType -eq “Folder”) {
Get-PermissionDetails $Item “Folder” $Item.FieldValues.FileLeafRef $Item.FieldValues.FileRef
}
}
}
# Export Report
$PermissionData |
Sort-Object ObjectURL, UserUPN -Unique |
Export-Csv -Path $ReportOutput -NoTypeInformation -Encoding UTF8
Write-Host “Report Generated: $ReportOutput”
Output
- CSV file with full permission breakdown
- Can be used for audit, investigation, or review
Summary
This script provides a complete permission visibility solution for SharePoint, which is not available natively in Microsoft 365, enabling better security, governance, and compliance control.