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:
Install-Module -Name PnP.PowerShell -Scope CurrentUser
Verify installation:
Get-Module PnP.PowerShell -ListAvailable
2. Required Permissions (Very Important)
To successfully extract full permission details, the account must have:
Recommended
Minimum Required
Ability to:
3. Admin Role Requirements
Depending on scope:
For Single Site Reports
For Multiple Sites / Tenant-Level Execution
4. Authentication Method
Use modern authentication:
Connect-PnPOnline -Url “<SiteURL>” -Interactive
5. Environment Requirements
Windows machine or server
PowerShell 5.1 or PowerShell 7+
Internet access to Microsoft 365
6. Access Considerations
If permissions are missing:
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.