Get SharePoint Folder Permissions Using PowerShell

A few days earlier, my manager asked me to send a report about who had permission (including external users) to access the files stored in the SharePoint library. This library has multiple levels of subfolders, so I need to make a report on the files present in those subfolders as well. To achieve this requirement, I used PnP PowerShell.

In this article, I will explain how to use PnP PowerShell to get permissions for each file in the SharePoint document library.

PnP PowerShell to Get SharePoint Library File Permissions And Export Them to CSV

Here is the Excel file generated after running the PnP PowerShell script, containing the permissions and URLs for each folder and file in the SharePoint document library, along with the users’ emails and the groups they belong to.

get sharepoint library file permissions into an excel

Run the PnP PowerShell script below and provide the site URL, list name, and the file path where the Excel file needs to be stored.

$SiteURL="https://<teanant name>.sharepoint.com/sites/RetailManagementSite"
$ListName = "Employee Satisfaction Survey PDF Files"
$ReportFile="D:\Temp Folder\Employee Satisfaction Survey PDF Files.csv"
If (Test-Path $ReportFile) { Remove-Item $ReportFile }

Function Get-Library Permissions([Microsoft.SharePoint.Client.SecurableObject] $Object)
{
    Switch($Object.TypedObject.ToString())
    {
        "Microsoft.SharePoint.Client.ListItem"
        { 
            If($Object.FileSystemObjectType -eq "Folder")
            {
                $ObjectType = "Folder"
                #Get the URL of the Folder 
                $Folder = Get-PnPProperty -ClientObject $Object -Property Folder
                $ObjectTitle = $Object.Folder.Name
                $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.Folder.ServerRelativeUrl)
            }
            Else 
            {
                Get-PnPProperty -ClientObject $Object -Property File, ParentList
                If($Object.File.Name -ne $Null)
                {
                    $ObjectType = "File"
                    $ObjectTitle = $Object.File.Name
                    $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.File.ServerRelativeUrl)
                }
                else
                {
                    $ObjectType = "List Item"
                    $ObjectTitle = $Object["Title"]
                    #Get the URL of the List Item
                    $DefaultDisplayFormUrl = Get-PnPProperty -ClientObject $Object.ParentList -Property DefaultDisplayFormUrl                     
                    $ObjectURL = $("{0}{1}?ID={2}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $DefaultDisplayFormUrl,$Object.ID)
                }
            }
        }
        Default
        { 
            $ObjectType = "List or Library"
            $ObjectTitle = $Object.Title
            #Get the URL of the List or Library
            $RootFolder = Get-PnPProperty -ClientObject $Object -Property RootFolder     
            $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $RootFolder.ServerRelativeUrl)
        }
    }
    Get-PnPProperty -ClientObject $Object -Property HasUniqueRoleAssignments, RoleAssignments
  
    $HasUniquePermissions = $Object.HasUniqueRoleAssignments
    $PermissionCollection = @()
    Foreach($RoleAssignment in $Object.RoleAssignments)
    { 
        Get-PnPProperty -ClientObject $RoleAssignment -Property RoleDefinitionBindings, Member
        $PermissionType = $RoleAssignment.Member.PrincipalType
        $PermissionLevels = $RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name
        $PermissionLevels = ($PermissionLevels | Where { $_ -ne "Limited Access"}) -join ","
        If($PermissionLevels.Length -eq 0) {Continue}
        If($PermissionType -eq "SharePointGroup")
        {
    
            $GroupMembers = Get-PnPGroupMember -Identity $RoleAssignment.Member.LoginName
            If($GroupMembers.count -eq 0){Continue}
            $GroupUsers = ($GroupMembers | Select -ExpandProperty Title) -join "; "
            $Permissions = New-Object PSObject
            $Permissions | Add-Member NoteProperty Object($ObjectType)
            $Permissions | Add-Member NoteProperty Title($ObjectTitle)
            $Permissions | Add-Member NoteProperty URL($ObjectURL)
            $Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)
            $Permissions | Add-Member NoteProperty Users($GroupUsers)
            $Permissions | Add-Member NoteProperty Email($RoleAssignment.Member.Email)
            $Permissions | Add-Member NoteProperty Type($PermissionType)
            $Permissions | Add-Member NoteProperty Permissions($PermissionLevels)
            $Permissions | Add-Member NoteProperty GrantedThrough("SharePoint Group: $($RoleAssignment.Member.LoginName)")
            $PermissionCollection += $Permissions
        }
        Else
        {
            
            $Permissions = New-Object PSObject
            $Permissions | Add-Member NoteProperty Object($ObjectType)
            $Permissions | Add-Member NoteProperty Title($ObjectTitle)
            $Permissions | Add-Member NoteProperty URL($ObjectURL)
            $Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)
            $Permissions | Add-Member NoteProperty Users($RoleAssignment.Member.Title)
            $Permissions | Add-Member NoteProperty Email($RoleAssignment.Member.Email)
            $Permissions | Add-Member NoteProperty Type($PermissionType)
            $Permissions | Add-Member NoteProperty Permissions($PermissionLevels)
            $Permissions | Add-Member NoteProperty GrantedThrough("Direct Permissions")
            $PermissionCollection += $Permissions
        }
    }
    $PermissionCollection | Export-CSV $ReportFile -NoTypeInformation -Append
}
Function Generate-LibraryPermissionsReport()
{
[cmdletbinding()]
    Param 
    (    
        [Parameter(Mandatory=$false)] [String] $SiteURL, 
        [Parameter(Mandatory=$false)] [String] $ListName,         
        [Parameter(Mandatory=$false)] [String] $ReportFile,
        [Parameter(Mandatory=$false)] [switch] $ScanItemLevel,
        [Parameter(Mandatory=$false)] [switch] $IncludeInheritedPermissions
    )
    Try {
        Function Get-PnPListItemsPermission([Microsoft.SharePoint.Client.List]$List)
        {
            Write-host -f Yellow "`t `t Getting Permissions of List Items in the List:"$List.Title
   
            $ListItems = Get-PnPListItem -List $List -PageSize 500
   
            $ItemCounter = 0
            ForEach($ListItem in $ListItems)
            {
                If($IncludeInheritedPermissions)
                {
                    Get-LibraryPermissions -Object $ListItem
                }
                Else
                {
                    $HasUniquePermissions = Get-PnPProperty -ClientObject $ListItem -Property HasUniqueRoleAssignments
                    If($HasUniquePermissions -eq $True)
                    {
                        Get-LibraryPermissions -Object $ListItem
                    }
                }
                $ItemCounter++
                Write-Progress -PercentComplete ($ItemCounter / ($List.ItemCount) * 100) -Activity "Processing Items $ItemCounter of $($List.ItemCount)" -Status "Searching Unique Permissions in List Items of '$($List.Title)'"
            }
        }
            $List = Get-PnpList -Identity $ListName -Includes RoleAssignments
             
            Write-host -f Yellow "Getting Permissions of the List '$ListName'..."
            Get-LibraryPermissions -Object $List
 
            If($ScanItemLevel)
            {
                Get-PnPListItemsPermission -List $List
            }
        Write-host -f Green "`t List Permission Report Generated Successfully!" 
     }
    Catch {
        write-host -f Red "Error Generating List Permission Report!" $_.Exception.Message
   }
}
Connect-PnPOnline -URL $SiteURL -ClientId "Provide your client ID" -Interactive
$Web = Get-PnPWeb
Generate-LibraryPermissionsReport -SiteURL $SiteURL -ListName $ListName -ReportFile $ReportFile -ScanItemLevel

Here:

  • $SiteURL = Provide your SharePoint site URL.
  • $ListName =Provide your SharePoint list or library name.
  • $ReportFile = Provide the file path where the Excel file needs to be created.
  • In the Connect-PnPOnline command for the -ClientId property, provide the client ID that you’ve registered in the Microsoft Entra ID.

Here, the Get-LibraryPermissions function retrieves the permissions for the specified SharePoint object, such as a list, library, list item, folder, or file, and returns the results.

Function Get-LibraryPermissions
([Microsoft.SharePoint.Client.SecurableObject]$Object)
{
    Switch($Object.TypedObject.ToString())
    {
        "Microsoft.SharePoint.Client.ListItem"
        { 
            If($Object.FileSystemObjectType -eq "Folder")
            {
                $ObjectType = "Folder"
                #Get the URL of the Folder 
                $Folder = Get-PnPProperty -ClientObject $Object -Property Folder
                $ObjectTitle = $Object.Folder.Name
                $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.Folder.ServerRelativeUrl)
            }
            Else
            {
                Get-PnPProperty -ClientObject $Object -Property File, ParentList
                If($Object.File.Name -ne $Null)
                {
                    $ObjectType = "File"
                    $ObjectTitle = $Object.File.Name
                    $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.File.ServerRelativeUrl)
                }
                else
                {
                    $ObjectType = "List Item"
                    $ObjectTitle = $Object["Title"]
                    #Get the URL of the List Item
                    $DefaultDisplayFormUrl = Get-PnPProperty -ClientObject $Object.ParentList -Property DefaultDisplayFormUrl                     
                    $ObjectURL = $("{0}{1}?ID={2}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $DefaultDisplayFormUrl,$Object.ID)
                }
            }
        }
        Default
        { 
            $ObjectType = "List or Library"
            $ObjectTitle = $Object.Title
            $RootFolder = Get-PnPProperty -ClientObject $Object -Property RootFolder     
            $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $RootFolder.ServerRelativeUrl)
        }
    }
    Get-PnPProperty -ClientObject $Object -Property HasUniqueRoleAssignments, RoleAssignments
  
    $HasUniquePermissions = $Object.HasUniqueRoleAssignments
      
    $PermissionCollection = @()
    Foreach($RoleAssignment in $Object.RoleAssignments)
    { 
        Get-PnPProperty -ClientObject $RoleAssignment -Property RoleDefinitionBindings, Member
  
        $PermissionType = $RoleAssignment.Member.PrincipalType
     
        $PermissionLevels = $RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name
  
        $PermissionLevels = ($PermissionLevels | Where { $_ -ne "Limited Access"}) -join ","
  
        If($PermissionLevels.Length -eq 0) {Continue}
  
        If($PermissionType -eq "SharePointGroup")
        {
            $GroupMembers = Get-PnPGroupMember -Identity $RoleAssignment.Member.LoginName
                  
            If($GroupMembers.count -eq 0){Continue}
            $GroupUsers = ($GroupMembers | Select -ExpandProperty Title) -join "; "
  
            $Permissions = New-Object PSObject
            $Permissions | Add-Member NoteProperty Object($ObjectType)
            $Permissions | Add-Member NoteProperty Title($ObjectTitle)
            $Permissions | Add-Member NoteProperty URL($ObjectURL)
            $Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)
            $Permissions | Add-Member NoteProperty Users($GroupUsers)
            $Permissions | Add-Member NoteProperty Email($RoleAssignment.Member.Email)
            $Permissions | Add-Member NoteProperty Type($PermissionType)
            $Permissions | Add-Member NoteProperty Permissions($PermissionLevels)
            $Permissions | Add-Member NoteProperty GrantedThrough("SharePoint Group: $($RoleAssignment.Member.LoginName)")
            $PermissionCollection += $Permissions
        }
        Else
        {
            #Add the Data to Object
            $Permissions = New-Object PSObject
            $Permissions | Add-Member NoteProperty Object($ObjectType)
            $Permissions | Add-Member NoteProperty Title($ObjectTitle)
            $Permissions | Add-Member NoteProperty URL($ObjectURL)
            $Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)
            $Permissions | Add-Member NoteProperty Users($RoleAssignment.Member.Title)
            $Permissions | Add-Member NoteProperty Email($RoleAssignment.Member.Email)
            $Permissions | Add-Member NoteProperty Type($PermissionType)
            $Permissions | Add-Member NoteProperty Permissions($PermissionLevels)
            $Permissions | Add-Member NoteProperty GrantedThrough("Direct Permissions")
            $PermissionCollection += $Permissions
        }
    }
    $PermissionCollection | Export-CSV $ReportFile -NoTypeInformation -Append
}
  • It first checks the object type and whether it is a list, list item, file, or folder, and stores its URLs into $ObjectURL.
  • It also checks whether the object has unique permissions or inherited permissions.
  • This function also iterates over each role assignment for the object, fetches the type of user or group, the assigned permission levels, and who granted the permission.
  • Then, this function creates a list of permissions and exports them to an Excel file.

Then, the Generate-LibraryPermissionsReport() Function generates a permissions report for a SharePoint list, including item-level permissions.

Function Generate-LibraryPermissionsReport()
{
[cmdletbinding()]
    Param 
    (    
        [Parameter(Mandatory=$false)] [String] $SiteURL, 
        [Parameter(Mandatory=$false)] [String] $ListName,         
        [Parameter(Mandatory=$false)] [String] $ReportFile,
        [Parameter(Mandatory=$false)] [switch] $ScanItemLevel,
        [Parameter(Mandatory=$false)] [switch] $IncludeInheritedPermissions
    )
    Try {
        Function Get-PnPListItemsPermission([Microsoft.SharePoint.Client.List]$List)
        {
            Write-host -f Yellow "`t `t Getting Permissions of List Items in the List:"$List.Title
   
            $ListItems = Get-PnPListItem -List $List -PageSize 500
   
            $ItemCounter = 0
            ForEach($ListItem in $ListItems)
            {
                If($IncludeInheritedPermissions)
                {
                    Get-LibraryPermissions -Object $ListItem
                }
                Else
                {
                    $HasUniquePermissions = Get-PnPProperty -ClientObject $ListItem -Property HasUniqueRoleAssignments
                    If($HasUniquePermissions -eq $True)
                    {
                        Get-LibraryPermissions -Object $ListItem
                    }
                }
                $ItemCounter++
                Write-Progress -PercentComplete ($ItemCounter / ($List.ItemCount) * 100) -Activity "Processing Items $ItemCounter of $($List.ItemCount)" -Status "Searching Unique Permissions in List Items of '$($List.Title)'"
            }
        }
 
            $List = Get-PnpList -Identity $ListName -Includes RoleAssignments
             
            Write-host -f Yellow "Getting Permissions of the List '$ListName'..."
            Get-LibraryPermissions -Object $List
 
            If($ScanItemLevel)
            {
                Get-PnPListItemsPermission -List $List
            }
        Write-host -f Green "`t List Permission Report Generated Successfully!" 
     }
    Catch {
        write-host -f Red "Error Generating List Permission Report!" $_.Exception.Message
   }
}

Here,

  • This function gets the inputs from the variables, $SiteURL, $ListName, $ReportFile, $ScanItemLevel, $IncludeInheritedPermissions.
  • It calls the Get-PnPPermissions cmd to fetch permissions for the list.
  • If we include -ScanItemLevel while calling this function, it will also retrieve permissions for each item in the list.
  • It returns a permission report, including who has access to the library and its files and folders.
If (Test-Path $ReportFile) { Remove-Item $ReportFile }

In the provided file path, the output file is removed if it already exists.

Connect-PnPOnline -URL $SiteURL -ClientId 98979831-421-46wd-8e8b-35375d84-Interactive

This Connect-PnPOnline command will connect to the SharePoint site.

  • -URL = Taking the site url
  • -ClientId = Provide the client ID that you have registered in Microsoft Entra ID.
  • -Interactive = It will ask you to provide credentials while the script is running.
Get-PnPWeb

This Get-PnPWeb command will return the current web object.

Generate-LibraryPermissionsReport -SiteURL $SiteURL -ListName $ListName -ReportFile $ReportFile -ScanItemLevel -IncludeInheritedPermissions    

Here, we are calling the Generate-LibraryPermissionsReport function by providing the site URL, list name, and report file input values along with ScanItemLevel and IncludeInheritedPermissions properties.

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

In the image below, you can see the error; I faced this when I tried to run the above PnP PowerShell script with the credentials of a person who doesn’t have SharePoint Administrator permissions.

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
Access is denied. Exception from HRESULT 0x80070005 E_ACCESSDENIED

So, in the Microsoft 365 admin center for that user, I assigned the SharePoint Administrator role. After some time, I ran the PowerShell script again; this time, the error was gone. This is because the user needs to have proper SharePoint permissions for fetching the permissions for items present in the SharePoint list or library.

To provide SharePoint Administrator access for the user, open the Microsoft 365 admin center -> Users -> Active users -> Choose user -> Click on Roles -> Admin center access -> Add SharePoint Administrator permissions -> Save changes.

Access is denied while trying to get library permissions using pnp powershell

I hope you understand the PnP PowerShell script above to retrieve permissions for files, folders, and list items in the SharePoint list/library. In this article, I also showed an error that might occur when running this script and how to resolve it.

Follow this article if you are also trying to fetch the SharePoint library files and list item permissions in Excel. While running this script, if you encounter any issues, please let me know in the comments below.

You can also have a look at the following PowerShell articles below:

Power Apps functions free pdf

30 Power Apps Functions

This free guide walks you through the 30 most-used Power Apps functions with real business examples, exact syntax, and results you can see.

Download User registration canvas app

DOWNLOAD USER REGISTRATION POWER APPS CANVAS APP

Download a fully functional Power Apps Canvas App (with Power Automate): User Registration App