Copy Permissions from One User to Another in SharePoint using PowerShell
Permission management in SharePoint is always a complex task, especially in large environments. Granting permissions in SharePoint becomes cumbersome when you are trying to clone an existing user’s access rights. Consider this scenario: You have an existing user in a department granted access to various SharePoint web applications, sites, lists, files, etc., and when a new user joins this department, You-SharePoint Administrator get the requirement of adding a new user to all the places with same access rights as the existing team member!
How will you compare the access rights of an existing team member and grant access in bulk? He may be granted permission on various levels with different access rights. It would become very time-consuming to find and grant the same level of permissions to multiple users on multiple SharePoint objects. Existing users may be granted access as part of:
- Farm Administrator group and/or as part of web application policies
- Member of Site collection administrator group
- Permissions granted at site level either as part of SharePoint group or with direct permissions
- Permissions granted to list or libraries by breaking inheritance
- Access rights may be via List item or folder level permissions.
In short, permissions can be granted at the following levels in SharePoint:
Well, To copy permissions from one user to another user on the above levels, I’ve written this PowerShell script. It just scans all possible levels for the given source user’s access rights and grants permission to the target user.
PowerShell script to clone SharePoint User Permissions:
This script iterates through each level as in the above image and copies permissions between given users at List Item/Folder, Lists, Site, Site Collection, Web Application, and Farm levels. Just change the parameters for variables $SourceUser, $TargetUser, and $WebAppURL accordingly and run the script. You’ll find the script outputs logs on the screen, wherever it copies permissions.
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
#Function to copy user permissions
Function Copy-UserPermissions($SourceUserID, $TargetUserID, [Microsoft.SharePoint.SPSecurableObject]$Object)
{
#Determine the given Object type and Get URL of it
Switch($Object.GetType().FullName)
{
"Microsoft.SharePoint.SPWeb" { $ObjectType = "Site" ; $ObjectURL = $Object.URL; $web = $Object }
"Microsoft.SharePoint.SPListItem"
{
If($Object.Folder -ne $null)
{
$ObjectType = "Folder" ; $ObjectURL = "$($Object.Web.Url)/$($Object.Url)"; $web = $Object.Web
}
Else
{
$ObjectType = "List Item"; $ObjectURL = "$($Object.Web.Url)/$($Object.Url)" ; $web = $Object.Web
}
}
#Microsoft.SharePoint.SPList, Microsoft.SharePoint.SPDocumentLibrary, Microsoft.SharePoint.SPPictureLibrary,etc
Default { $ObjectType = "List/Library"; $ObjectURL = "$($Object.ParentWeb.Url)/$($Object.RootFolder.URL)"; $web = $Object.ParentWeb }
}
#Get Source and Target Users
$SourceUser = $Web.EnsureUser($SourceUserID)
$TargetUser = $Web.EnsureUser($TargetUserID)
#Get Permissions of the Source user on given object - Such as: Web, List, Folder, ListItem
$SourcePermissions = $Object.GetUserEffectivePermissionInfo($SourceUser)
#Iterate through each permission and get the details
ForEach($SourceRoleAssignment in $SourcePermissions.RoleAssignments)
{
#Get all permission levels assigned to User account directly or via SharePOint Group
$SourceUserPermissions=@()
ForEach($SourceRoleDefinition in $SourceRoleAssignment.RoleDefinitionBindings)
{
#Exclude "Limited Accesses"
If($SourceRoleDefinition.Name -ne "Limited Access")
{
$SourceUserPermissions += $SourceRoleDefinition.Name
}
}
#Check Source Permissions granted directly or through SharePoint Group
If($SourceUserPermissions)
{
If($SourceRoleAssignment.Member -is [Microsoft.SharePoint.SPGroup])
{
$SourcePermissionType = "'Member of SharePoint Group - " + $SourceRoleAssignment.Member.Name +"'"
#Add Target User to the Source User's Group
#Get the Group
$Group = [Microsoft.SharePoint.SPGroup]$SourceRoleAssignment.Member
#Check if user is already member of the group - If not, Add to group
if( ($Group.Users | where {$_.UserLogin -eq $TargetUserID}) -eq $null )
{
#Add User to Group
$Group.AddUser($TargetUser)
#Write-Host Added to Group: $Group.Name
}
}
else
{
$SourcePermissionType = "Direct Permission"
#Add Each Direct permission (such as "Full Control", "Contribute") to Target User
ForEach($NewRoleDefinition in $SourceUserPermissions)
{
#Role assignment is a linkage between User object and Role Definition
$NewRoleAssignment = New-Object Microsoft.SharePoint.SPRoleAssignment($TargetUser)
$NewRoleAssignment.RoleDefinitionBindings.Add($web.RoleDefinitions[$NewRoleDefinition])
$object.RoleAssignments.Add($NewRoleAssignment)
$object.Update()
}
}
$SourceUserPermissions = $SourceUserPermissions -join ";"
Write-Host "***$($ObjectType) Permissions Copied: $($SourceUserPermissions) at $($ObjectURL) via $($SourcePermissionType)***"
}
}
}
Function Clone-SPUser($SourceUserID, $TargetUserID, $WebAppURL)
{
###Check Whether the Source Users is a Farm Administrator ###
Write-host "Scanning Farm Administrators Group..."
#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 administrators groups
ForEach ($user in $FarmAdminGroup.users)
{
If($User.LoginName.Endswith($SourceUserID,1)) #1 to Ignore Case
{
#Add the target user to Farm Administrator Group
$FarmAdminGroup.AddUser($TargetUserID,[string]::Empty,$TargetUserID , [string]::Empty)
Write-Host "***Added to Farm Administrators Group!***"
}
}
### 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($SourceUserID,1))
{
#Write-Host $Policy.UserName
$PolicyRoles=@()
ForEach($Role in $Policy.PolicyRoleBindings)
{
$PolicyRoles+= $Role
}
}
}
#Add Each Policy found
If($PolicyRoles)
{
$WebAppPolicy = $WebApp.Policies.Add($TargetUserID, $TargetUserID)
ForEach($Policy in $PolicyRoles)
{
$WebAppPolicy.PolicyRoleBindings.Add($Policy)
}
$WebApp.Update()
Write-host "***Added to Web application Policies!***"
}
### Drill down to Site Collections, Webs, Lists & Libraries, Folders and List items ###
#Get all Site collections of given web app
$SiteCollections = Get-SPSite -WebApplication $WebAppURL -Limit All
#Convert UserID Into Claims format - If WebApp is claims based! Domain\User to i:0#.w|Domain\User
If( (Get-SPWebApplication $WebAppURL).UseClaimsAuthentication)
{
$SourceUserID = (New-SPClaimsPrincipal -identity $SourceUserID -identitytype 1).ToEncodedString()
$TargetUserID = (New-SPClaimsPrincipal -identity $TargetUserID -identitytype 1).ToEncodedString()
}
#Loop through all site collections
Foreach($Site in $SiteCollections)
{
#Prepare the Target user
$TargetUser = $Site.RootWeb.EnsureUser($TargetUserID)
Write-host "Scanning Site Collection Administrators Group for:" $site.Url
###Check Whether the User is a Site Collection Administrator
Foreach($SiteCollAdmin in $Site.RootWeb.SiteAdministrators)
{
If($SiteCollAdmin.LoginName.EndsWith($SourceUserID,1))
{
#Make the user as Site collection Admin
$TargetUser.IsSiteAdmin = $true
$TargetUser.Update()
Write-host "***Added to Site Collection Admin Group***"
}
}
#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
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions $SourceUserID $TargetUserID $Web
}
#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))
{
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions $SourceUserID $TargetUserID $List
}
#Check Folders with Unique Permissions
$UniqueFolders = $List.Folders | where { $_.HasUniqueRoleAssignments -eq $True }
#Get Folder permissions
If($UniqueFolders)
{
Foreach($folder in $UniqueFolders)
{
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions $SourceUserID $TargetUserID $folder
}
}
#Check List Items with Unique Permissions
$UniqueItems = $List.Items | where { $_.HasUniqueRoleAssignments -eq $True }
If($UniqueItems)
{
#Get Item level permissions
Foreach($item in $UniqueItems)
{
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions $SourceUserID $TargetUserID $Item
}
}
}
}
}
Write-Host "Permission are copied successfully!"
}
#Define variables for processing
$WebAppURL = "https://sharepoint.crescent.com"
#Provide input for source and Target user Ids
$SourceUser ="Crescent\TonyW"
$TargetUser ="Crescent\Salaudeen"
#Call the function to clone user access rights
Clone-SPUser $SourceUser $TargetUser $WebAppURL
Copy User Permissions at list level:
This script is broken into two functions: Copy-UserPermissions and Clone-SPSuer for convenience. Let’s say you want to copy permissions at the list level, then you can utilize the Copy-UserPermission function as:
$WebURL = "https://sharepoint.crescent.com/sites/sales"
$web = Get-SPWeb $WebURL
$SourceUser ="i:0#.w|Crescent\TonyW"
$TargetUser ="i:0#.w|Crescent\Salaudeen"
$list = $Web.Lists["Invoice"]
#$folder = $list.Folders[0]
#$ListItem = $list.Items[0]
#Call the function to copy user permissions programmatically at LIST level
Copy-UserPermissions $SourceUser $TargetUser $list
This script clones user permissions at list level (copies at list level only, no drill-down to Folders and Items!).
Clone User Permissions from a CSV file:
When you have to copy permissions for multiple users, you can use a CSV file and the PowerShell script. Here is an example:
Create a CSV File in this format and populate it according to your requirements:
Use this PowerShell script to read from CSV file and copy user permissions:
$CSVFilePath = "C:\temp\CloneUsers.csv"
#Get the CSV file
$CSVFile = Import-Csv $CSVFilePath
#Read CSV file and create document document library
ForEach($Line in $CSVFile)
{
#Get CSV File Entries
$WebAppURL = $Line.WebAppURL
$SourceUser = $Line.SourceUser
$TargetUser = $Line.TargetUser
#Call the Function to Clone user permissions
Clone-SPUser $SourceUser $TargetUser $WebAppURL
}
Is this available for Sharepoint Online? Or PnP alternative?
I am looking for a solution to copy permissions in a document library.
Very nice script!
Btw, I receive this error:
Exception calling “GetUserEffectivePermissionInfo” with “1” argument(s): “Operation is not valid due to the current
state of the object.”
At C:\Aggiunte\Copia_diritti_utente_sharepoint.ps1:30 char:5
+ $SourcePermissions = $Object.GetUserEffectivePermissionInfo($SourceUser)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
I already tried to add as suggested on technet, but it doesn’t change…
Hello! Is there a way to do that on M365? Thanks in advanced 🙂
Excellent work and save my day – Nagaraju Pattem
Is script available for O365 SharePoint Online
Is there script available for O365 sharepoint online
Great script, and I think it can do the job. However I’m having issues. Since my site collection runs on forms authenticatio I have to use the “i:0#.f|wcfmembershipprovider” prefix. And then Powershell appends the windows provider so I get an error message saying: “The specified user i:0#.w|i%3a0#.f%7cwcfmembershipprovider%7cusername could not be found.”
Any ideas on how I can escape charactersand how I can tell powershell to use the forms authentication rather than windows?
Thank you!
OT
Did you ever get this error to go away? If so what did you do?
Great Script! Can you skip if everyone group already has permissions?
dear can we make this script read the source user and target user from an excel sheet i have a lot of users ?
Article updated with bulk cloning user rights using CSV File!
Awesome. Could you please help putting script to run for bulk users using csv file
Great script!
Any idea for copy permissions between SharePoint groups?
The script worked well. However, it’s little buggy. I have some groups where domainall users are listed and this script added target user in the SP group. I had to do some clean up.
Thank you so much for creating this script.
Does this script overwrite an existing user’s set permissions in Sharepoint? Or does it just add extra permissions where an existing user may have had read permissions to a site?
This script appends permissions to the existing one!
Thank you for the script. This is to clone individual users. How about bulk using a csv file?
Wonderful Script which saved my time but i am getting below error message. Please help me to resolve.
***List/Library Permissions Copied: Read at https://insite.mfxservices.intr/it/Pr
oject Stabilization via ‘Member of SharePoint Group – MFX (inSite) – MFX Readers
‘***
s : The term ‘s’ is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At D:ControlPoint_ReplaceScriptClone-SPUser.ps1:13 char:4
+ {s
+ ~
+ CategoryInfo : ObjectNotFound: (s:String) [], CommandNotFoundEx
ception
+ FullyQualifiedErrorId : CommandNotFoundException
s : The term ‘s’ is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At D:ControlPoint_ReplaceScriptClone-SPUser.ps1:13 char:4
+ {s
+ ~
+ CategoryInfo : ObjectNotFound: (s:String) [], CommandNotFoundEx
ception
+ FullyQualifiedErrorId : CommandNotFoundException
Read more: https://www.sharepointdiary.com/2015/01/clone-sharepoint-user-permissions-using-powershell.html#ixzz4qktgFa41
there is a typeerror: delete the “s”..than its working correctly
Hi Salaudeen,
Wonderful Script which saved my time but i am getting below error message. Please help me to resolve.
***List/Library Permissions Copied: Read at https://insite.mfxservices.intr/it/Pr
oject Stabilization via ‘Member of SharePoint Group – MFX (inSite) – MFX Readers
‘***
s : The term ‘s’ is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At D:ControlPoint_ReplaceScriptClone-SPUser.ps1:13 char:4
+ {s
+ ~
+ CategoryInfo : ObjectNotFound: (s:String) [], CommandNotFoundEx
ception
+ FullyQualifiedErrorId : CommandNotFoundException
s : The term ‘s’ is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At D:ControlPoint_ReplaceScriptClone-SPUser.ps1:13 char:4
+ {s
+ ~
+ CategoryInfo : ObjectNotFound: (s:String) [], CommandNotFoundEx
ception
+ FullyQualifiedErrorId : CommandNotFoundException
This is very excellent script however there is one minor issue. If the any user group has permission as “everyone” then in this case the script is adding the targeted user in this group where as this was not required to add.
I am getting the following error when running this script
You cannot call a method on a null-valued expression.
At line:313 char:40
+ if($SiteCollAdmin.LoginName.EndsWith <<<< ($SourceUserID,1)) + CategoryInfo : InvalidOperation: (EndsWith:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull Clone-SPUser : Exception has been thrown by the target of an invocation. At line:447 char:13 + Clone-SPUser <<<< $SourceUser $TargetUser $WebAppURL + CategoryInfo : NotSpecified: (:) [Clone-SPUser], TargetInvocationException + FullyQualifiedErrorId : System.Reflection.TargetInvocationException,Clone-SPUser
Fantastic…
What a lifesaver! Thank you!
Very nice script ! Thanks a lot
Why on sp2010 throw so many exception like :
GetType : You cannot call a method on a null-valued expression.
At C:UsersmossadmDesktopCloneUser.PS1:8 char:23
+ 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 C:UsersmossadmDesktopCloneUser.PS1:31 char:60 + $SourcePermissions = $Object.GetUserEffectivePermissionInfo <<<< ($SourceUser ) + CategoryInfo : InvalidOperation: (GetUserEffectivePermissionInf o:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull
Im getting the same error ?? Any resolution to this?
Script Updated!
Thanks for the great script. however there are errors as mentioned in comments above… the errors are due to null values at line 192
$UniqueFolders = $List.Folders | where { $_.HasUniqueRoleAssignments -eq $True }
#Get Folder permissions
foreach($folder in $UniqueFolders) —– Here the $folder object is getting picked up, even if the $UniqueFolders is null arrray
It can be handled as follows:
if ($UniqueFolders -eq $null)
{ }
else
{
#Get Folder permissions
foreach($folder in $UniqueFolders)
{
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions $SourceUserID $TargetUserID $folder
}
}
Similary for the section for the $UniqueItems….
Fixed!
Hi, great script, just the thing we where looking for.
But i get a lot of error’s (no not de access denied):
Sometimes it seems like my object is empty (Site/List/Folder/Listitem) how can that be?
And ther is no check on limited Access permission level ==> had to catch try that block.
Limited access can’t be copied! AFAIK.
Idd that’s true, but you’ve should check on it no?
Does it also check if the user is permitted by an Active Directory group? Or would it be possible to extend the script checking that and adding the new account using a sharepoint group or give direct access at that site/item…?
Nope! This script doesn’t clone Active Directory groups Permissions!
Wonderful script Salaudeen but for some reason it is not adding the target user to any groups my source user is a member of. Any ideas why that might be?
I would recommend to run this script from FARM ADMIN account.