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:

When This is Required

Use this approach when:

What the Report Includes

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

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

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.