SharePoint 2013 Specific User Permission Analysis Report using PowerShell

Analyzing SharePoint permissions for a particular user is often a common task in SharePoint administration. Generally, How do we check what permissions a user has on SharePoint content? By getting into the site or list settings page and check permissions for the particular user, isn’t it? Well, You may want to analyze the particular user’s permissions for your entire SharePoint environment.  How about that? Each and every SharePoint site, list, library, folder, and list items may have unique permissions. It can even go more challenging when you have multiple SharePoint farms.

Well, PowerShell is a lifesaver! Here is my permission reporting solution to scan and provide a report to view a user’s permission on the SharePoint web application. With this script, you can analyze and track the security effectively! Check what permissions on an account have been granted in all places in SharePoint. This PowerShell script scans the below areas to retrieve a specific user’s access rights:

  • Farm administrator’s group
  • Central administration web application policies
  • Site collection administrators 
  • Scans all site collections and sub-sites with unique permissions in which user has access.
  • Scans all lists and libraries with unique permissions in which user has access.
  • Scans all folders and list Items which has permissions in the site in which user has access.

Just change the Input variables section and provide parameters for User Id, Web Application and Report path variables and run the script in PowerShell.

After generating a SharePoint permissions report, this script generates a CSV file, which can be export as an excel file to allows further research and analysis outside of a SharePoint environment. It gets data such as: Object, Title, URL, Permission Type, Permissions as in the below screenshot.

sharepoint User Permission Analysis Report

PowerShell Script to Generate User Permission Report in SharePoint 2010/2013

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Function to retrieve Permission data
Function Get-PermissionInfo([String]$UserID, [Microsoft.SharePoint.SPSecurableObject]$Object)
{
    #Object Array to hold Permission data
    $PermissionDataCollection = @()
    if($Object)
    {
       #Determine the given Object type and Get URL of it
       switch($Object.GetType().FullName)
       {
           "Microsoft.SharePoint.SPWeb"  { $ObjectType = "Site" ; $ObjectURL = $Object.URL }
           "Microsoft.SharePoint.SPListItem" 
           { 
           if($Object.Folder -ne $null)
           {
               $ObjectType = "Folder" ; $ObjectURL = "$($Object.Web.Url)/$($Object.Url)" 
           }
           else
           {
               $ObjectType = "List Item"; $ObjectURL = "$($Object.Web.Url)/$($Object.Url)" 
           }
       }
       #Microsoft.SharePoint.SPList, Microsoft.SharePoint.SPDocumentLibrary, "Microsoft.SharePoint.SPPictureLibrary",etc
       default { $ObjectType = "List/Library"; $ObjectURL = "$($Object.ParentWeb.Url)/$($Object.RootFolder.URL)" }
    }
 
   #Get Permissions of the user on given object - Such as: Web, List, Folder, ListItem
   $UserPermissionInfo = $Object.GetUserEffectivePermissionInfo($UserID)

   #Iterate through each permission and get the details
   foreach($UserRoleAssignment in $UserPermissionInfo.RoleAssignments)
   {
        #Get all permission levels assigned to User account directly or via SharePOint Group
        [email protected]()
        foreach ($UserRoleDefinition in $UserRoleAssignment.RoleDefinitionBindings)
        {
            #Exclude "Limited Accesses"
            if($UserRoleDefinition.Name -ne "Limited Access")
            {
                 $UserPermissions += $UserRoleDefinition.Name
            }
        }
 
      #Determine Permissions granted directly or through SharePoint Group
      if($UserPermissions)
      {
          if($UserRoleAssignment.Member -is [Microsoft.SharePoint.SPGroup])   
          {
              $PermissionType = "Member of SharePoint Group: " + $UserRoleAssignment.Member.Name     
          }
      else
      {
            $PermissionType = "Direct Permission"
      }
        $UserPermissions = $UserPermissions -join ";"  
 
         #Create an object to hold storage data
         $PermissionData = New-Object PSObject
         $PermissionData | Add-Member -type NoteProperty -name "Object" -value $ObjectType
         $PermissionData | Add-Member -type NoteProperty -name "Title" -value $Object.Title
         $PermissionData | Add-Member -type NoteProperty -name "URL" -value $ObjectURL  
         $PermissionData | Add-Member -type NoteProperty -name "Permission Type" -value $PermissionType
         $PermissionData | Add-Member -type NoteProperty -name "Permissions" -value $UserPermissions
         $PermissionDataCollection += $PermissionData
       }    
    }  
    Return $PermissionDataCollection
  }
}

#Function to Generate Permission Report
Function Generate-PermissionReport($UserID, $WebAppURL, $ReportPath)
{
    #Output Report location, delete the file, If already exist!
    if (Test-Path $ReportPath)
     {
        Remove-Item $ReportPath
     }
  
    #Write Output Report CSV File Headers
    "Object, Title, URL, Permission Type, Permissions" | out-file $ReportPath

    ###Check Whether the Search Users is a Farm Administrator ###
    Write-host "Scanning Farm Administrators..." 
    #Get the SharePoint Central Administration site
    $AdminWebApp = Get-SPwebapplication -includecentraladministration | where {$_.IsAdministrationWebApplication}
    $AdminSite = Get-SPWeb $AdminWebApp.Url
    $AdminGroupName = $AdminSite.AssociatedOwnerGroup
    $FarmAdminGroup = $AdminSite.SiteGroups[$AdminGroupName]
 
    #enumerate in farm adminidtrators groups
    foreach ($user in $FarmAdminGroup.users)
    {
      if($user.LoginName.Endswith($UserID,1)) #1 to Ignore Case
      {
       "Farm, $($AdminSite.Title), $($AdminWebApp.URL), Farm Administrators Group, Farm Administrator" | Out-File $ReportPath -Append
     }     
    }
 
   ### Check Web Application User Policies ###
  Write-host "Scanning Web Application Policies..." 
  $WebApp = Get-SPWebApplication $WebAppURL
 
  foreach ($Policy in $WebApp.Policies)
  {
      #Check if the search users is member of the group
      if($Policy.UserName.EndsWith($UserID,1))
      {
         #Write-Host $Policy.UserName
         [email protected]()
         foreach($Role in $Policy.PolicyRoleBindings)
         {
            $PolicyRoles+= $Role.Name +";"
         }
          #Send Data to CSV File
          "Web Application, $($WebApp.Name), $($WebApp.URL), Web Application Policy, $($PolicyRoles)" | Out-File $ReportPath -Append
      }
  }

    #Convert UserID Into Claims format - If WebApp is claims based! Domain\User to i:0#.w|Domain\User
    if($WebApp.UseClaimsAuthentication)
    {
        $ClaimsUserID = (New-SPClaimsPrincipal -identity $UserID -identitytype 1).ToEncodedString()
    }
     else
    {
        $ClaimsUserID = $UserID
    }
 #Get all Site collections of given web app
 $SiteCollections = Get-SPSite -WebApplication $WebAppURL -Limit All

    #Loop through all site collections 
    foreach($Site in $SiteCollections)
    {
       Write-host "Scanning Site Collection:" $site.Url
       ###Check Whether the User is a Site Collection Administrator
       foreach($SiteCollAdmin in $Site.RootWeb.SiteAdministrators)
       {
          if($SiteCollAdmin.LoginName.EndsWith($ClaimsUserID,1))
          {
            "Site Collection, $($Site.RootWeb.Title), $($Site.RootWeb.Url), Site Collection Administrators Group, Site Collection Administrator" | Out-File $ReportPath -Append
          }     
      }
  
  #Get all webs
  $WebsCollection = $Site.AllWebs
  #Loop throuh each Site (web)
  foreach($Web in $WebsCollection)
  {
       if($Web.HasUniqueRoleAssignments -eq $True)
       {
          Write-host "Scanning Site:" $Web.Url
    
          #Get Permissions of the user on Web
          $WebPermissions = Get-PermissionInfo $ClaimsUserID $Web
     
          #Export Web permission data to CSV file - Append
          $WebPermissions |  Export-csv $ReportPath  -notypeinformation -Append 
       } 
    
    #Check Lists with Unique Permissions
    Write-host "Scanning Lists on $($web.url)..."
    foreach($List in $web.Lists)
    {
        if($List.HasUniqueRoleAssignments -eq $True -and ($List.Hidden -eq $false))
        {
             #Get Permissions of the user on list
             $ListPermissions = Get-PermissionInfo $ClaimsUserID $List
      
            #Export Web permission data to CSV file - Append
            $ListPermissions |  Export-csv $ReportPath -notypeinformation -Append       
        }
    
     #Check Folders with Unique Permissions
     $UniqueFolders = $List.Folders | where { $_.HasUniqueRoleAssignments -eq $True }                    
     #Get Folder permissions
     foreach($folder in $UniqueFolders)
     {
         $FolderPermissions = Get-PermissionInfo $ClaimsUserID $folder
    
         #Export Folder permission data to CSV file - Append
         $FolderPermissions |  Export-csv $ReportPath -notypeinformation -Append    
      }
    
     #Check List Items with Unique Permissions
     $UniqueItems = $List.Items | where { $_.HasUniqueRoleAssignments -eq $True }
     #Get Item level permissions
     foreach($item in $UniqueItems)
     {
         $ItemPermissions = Get-PermissionInfo $ClaimsUserID $Item
      
         #Export List Items permission data to CSV file - Append
         $ItemPermissions |  Export-csv $ReportPath -notypeinformation -Append    
     }
    }
  }
 }
 Write-Host Permission Report Generated successfully!
}

#Input Variables
$WebAppURL = "http://intranet.crescent.com"
$Userid ="Crescent\Salaudeen" 
$ReportPath = "D:\Reports\PermissionRpt.csv"

#Call the function to generate user access report
Generate-PermissionReport $Userid $WebAppURL $ReportPath

You can also download the script from TechNet gallery: SharePoint Permission Report: Check Access Rights for a Specific User

This script is broken into two functions. So that you can use the first function: Get-PermissionInfo to get permissions data scoped to a site collection permission report/site. Above script scoped at a particular web application. You can call the same function on all your web application to get the entire SharePoint permissions reports.

PowerShell Scripts to generate SharePoint Permission Reports:

Here is my list of PowerShell scripts to create various reports for SharePoint permission auditing.

3rd Party Tools:
There are many tools in the market to analyze, audit SharePoint user permissions (and more features naturally!). Here are some:

Salaudeen Rajack

Salaudeen Rajack is a SharePoint Architect with Two decades of SharePoint Experience. He loves sharing his knowledge and experiences with the SharePoint community, through his real-world articles!

25 thoughts on “SharePoint 2013 Specific User Permission Analysis Report using PowerShell

  • September 13, 2018 at 2:27 PM

    Shall we use this for SharePoint online?

    Reply
  • February 9, 2017 at 5:19 PM

    Is there a way to determine if an Active Directory user account was used versus an Active Directory group? Is there an attribute to check to see if its one or the other. I’m trying to create a report that shows me where individual user accounts are set instead of using their AD role group.

    Reply
    • February 12, 2017 at 9:19 AM

      Try this: https://www.sharepointdiary.com/2016/02/sharepoint-site-collection-permission-report-powershell-script.html

      Reply
  • January 19, 2017 at 3:27 PM

    I am unable to get this script to work on my 2010 SP farm. I am running Classic/NTLM authentication. I am not using claims.

    Can you please help me?

    All I do is change the parameters at the very bottom, the URL and the User ID, and the location of the CSV file.

    I get the following errors, (It states the user does not exist, but I know 10000% my own ID does exist)..

    GetUserEffectivePermissionInfo : Exception calling “GetUserEffectivePermissionI
    nfo” with “1” argument(s): “The user does not exist or is not unique.”
    At line:24 char:62
    + $UserPermissionInfo = $Object.GetUserEffectivePermissionInfo <<<< ($UserID) + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException Export-csv : A parameter cannot be found that matches parameter name 'Append'. At line:73 char:75 + $WebPermissions | Export-csv $ReportPath -notypeinformation -Append << << + CategoryInfo : InvalidArgument: (:) [Export-Csv], ParameterBind ingException + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Comm ands.ExportCsvCommand Scanning Lists on http://portal10a:31437... GetUserEffectivePermissionInfo : Exception calling "GetUserEffectivePermissionI nfo" with "1" argument(s): "The user does not exist or is not unique." At line:24 char:62 + $UserPermissionInfo = $Object.GetUserEffectivePermissionInfo <<<< ($UserID) + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException Export-csv : A parameter cannot be found that matches parameter name 'Append'. At line:84 char:76 + $ListPermissions | Export-csv $ReportPath -notypeinformation -Append < <<< + CategoryInfo : InvalidArgument: (:) [Export-Csv], ParameterBind ingException + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Comm ands.ExportCsvCommand GetType : You cannot call a method on a null-valued expression. At line:6 char:27 + switch($Object.GetType <<<< ().FullName) + CategoryInfo : InvalidOperation: (GetType:String) [], RuntimeEx ception + FullyQualifiedErrorId : InvokeMethodOnNull GetUserEffectivePermissionInfo : You cannot call a method on a null-valued expr ession. At line:24 char:62 + $UserPermissionInfo = $Object.GetUserEffectivePermissionInfo <<<< ($UserID) + CategoryInfo : InvalidOperation: (GetUserEffectivePermissionInf o:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull

    Reply
    • September 7, 2017 at 4:58 AM

      Having the same issue. where you able to figure it out?

      Reply
    • January 2, 2018 at 10:13 AM

      Same issue in SP2013 for a user that is member of the ownergroup. Did you figure it out?

      Reply
  • January 3, 2017 at 11:42 AM

    Hello, can import all csv information with another user but with all information included in the csv file generated??

    Example:
    Your Script Export all information to the user:contosooldUser
    I need a script to import this info to user: contosonewUser

    I need Help please!

    Thanks

    Reply
    • January 3, 2017 at 3:17 PM

      You mean: You want to copy OldUser’s permissions to NewUser? or Replace OldUser premissions with NewUser? Refer these posts
      https://www.sharepointdiary.com/2015/01/clone-sharepoint-user-permissions-using-powershell.html
      https://www.sharepointdiary.com/2014/12/migrate-sharepoint-users-from-one-domain-to-another.html

      Reply
  • May 25, 2016 at 1:49 PM

    Hi, is this script going to work on MOSS 2007?

    Reply
  • February 3, 2016 at 1:52 PM

    Hi Salaudeen..

    You have written a great script for SharePoint admins. I have exactly same requirements but it’s for all users including folder permissions if it’s unique folder permissions.

    I have seen comments that other user are looking for the same i.e. for all users.
    Function Get-PermissionInfo([String]$UserID, [Microsoft.SharePoint.SPSecurableObject]$Object)

    requires userID and I tried to use this function that accepts only the $Object but not able to managed all users using your script.

    Any pointer would be greatly appreciated.

    Reply
  • December 21, 2015 at 1:52 PM

    Is it possible to skip some groups like Style Resource Readers?

    Can I change this script to only show direct permissions and not permssions given via an ad group?

    Reply
    • December 21, 2015 at 2:44 PM

      Yes! Add your group name in Line#38: if($UserRoleDefinition.Name -ne “Limited Access”)

      This script doesn’t count permissions granted via AD Groups!

      Reply
  • September 15, 2015 at 6:09 PM

    Is this for On-Prem only?

    Reply
    • September 16, 2015 at 6:07 AM

      Yes! Its written for On-Prem. However, its possible to make one for O365 by leaving Farm & Web App sections.

      Reply
    • April 4, 2017 at 5:09 PM

      Hi,

      Could you please help me in getting the same report for O365.

      Thanks in Advance.

      Reply
  • July 22, 2015 at 9:13 PM

    I attempted really hard to reverse engineer this script to find out why it keeps failing for me, but I can’t figure out why. I’m even attempting to run this with the SharePoint 2010 Management shell with the full out sharepoint farm admin account and all I get is this constantly:

    You cannot call a method on a null-valued expression.
    At C:tempUserAccessReport.ps1:135 char:49
    + if($SiteCollAdmin.LoginName.EndsWith <<<< ($ClaimsUserID,1)) + CategoryInfo : InvalidOperation: (EndsWith:String) [], RuntimeE xception + FullyQualifiedErrorId : InvokeMethodOnNull Generate-PermissionReport : Exception has been thrown by the target of an invoc ation. At C:tempUserAccessReport.ps1:203 char:26 + Generate-PermissionReport <<<< $Userid $WebAppURL $ReportPath + CategoryInfo : NotSpecified: (:) [Generate-PermissionReport], T argetInvocationException + FullyQualifiedErrorId : System.Reflection.TargetInvocationException,Gene rate-PermissionReport Thoughts?

    Reply
  • June 30, 2015 at 9:57 PM

    Instead of finding all the sites a specific user has access to, I need to find all the sites that ‘everyone’ has access to. Is it possible to modify your script to do this?

    Reply
    • August 3, 2015 at 7:47 AM

      You mean get permission report for “All Users” instead of one specific user? Well, Just remove IF blocks from the script. Such as:
      If($user.LoginName.Endswith($UserID,1)),
      If($Policy.UserName.EndsWith($UserID,1))
      If($SiteCollAdmin.LoginName.EndsWith($ClaimsUserID,1))

      Reply
    • September 24, 2015 at 9:21 PM

      i commented the 3 IF loop you mentioned. How do i call the function to list all users ?

      like this ?
      generate-permissionreport $WebappUrl $ReportPath$

      Reply
    • September 26, 2015 at 7:51 AM

      This script enumerates through all users who has permission on particular object such as Farm, Web App Policy, Site collection, List, etc. These IF condition checks whether the given user account matches while enumerating. Removing IF gets you all users who has access.

      Reply

Leave a Reply