SharePoint: Remove Orphan Users


Introduction

This article explains to remove orphan users from SharePoint without affecting the metadata.

Applies To

The examples demonstrated below are tested with and apply to the following versions of SharePoint:

  • SharePoint 2019
  • SharePoint 2016
  • SharePoint 2013
  • SharePoint 2010

PowerShell Script

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
 
Start-Transcript -Path ".\RemoveOrphanedUsers-Transcript-$(Get-Date -f yyyyMMdd-HHmmss).txt" -NoClobber
 
Function Check-UserExistsInAD()
{  
 Param
 ( 
 [Parameter(Mandatory=$true, Position=0)] [string]$UserLoginID,
 [Parameter(Mandatory=$true, Position=2)] [string[]]$forestDomains
 )
  
 ForEach ($Domain in  $forestDomains)
 {
 Try
 {
 $context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain", $Domain)
 $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($context)
  
 #$root = $domain.GetDirectoryEntry()
 $search = [System.DirectoryServices.DirectorySearcher]$domain.GetDirectoryEntry()
 $search.Filter = "(&(objectCategory=User)(samAccountName=$UserLoginID))"
 $result = $search.FindAll()
  
 if ($result -ne $null)
 {
 return $true
 }
 }
 Catch
 {
 Write-host "Error while checking the user identity in active directory - " $_.Exception.Message
 }
 }
 Return $false
}
Try
{  
 $domains = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Domains
 $sites = Get-SPWebApplication -IncludeCentralAdministration | Get-SPSite -Limit All | Select URL -ErrorAction Stop  
 #$sites="http://sharepoint/sites/site1","http://sharepoint/sites/site2"
 Write-host "================================ Started ==========================================="
 ForEach($siteColl in  $sites)
 {
 Try
 { 
 $siteUrl = $siteColl.Url  
 $site = Get-SPSite -Identity $siteUrl | Select URL,RootWeb  
 ForEach($User in  $site.RootWeb.SiteUsers)
 {  
 Try
 {  
 $userDisplaName=$User.DisplayName.ToLower()
 $userLoginName=$User.LoginName.ToLower()  
 $AccountName = $userLoginName.split("\")[1]  #Domain\[UserName]  
 #Exclude Built-in User Accounts , Security Groups
 If((!$User.IsDomainGroup) -and
 ($userLoginName -ne "nt authority\authenticated users") -and 
 ($userLoginName -ne "sharepoint\system") -and
 ($userLoginName -ne "nt authority\local service")
 )
 {
 If ((Check-UserExistsInAD $AccountName $domains) -eq $false )
 {
 Write-host "Found orphan user $userLoginName ($userDisplaName) from the site - " $siteUrl  
 $site.RootWeb.SiteUsers.Remove($userLoginName)
 $site.RootWeb.Update()  
 Write-host "Removed orphan user "  $userLoginName "("$userDisplaName ") from the site - "  $siteUrl
 }  
 }  
 }
 Catch
 {
 Write-host "Error while getting user details - $userDisplaName ($userLoginName) -  from site - " $siteUrl " - " $_.Exception.Message
 }  
 }
  
 }
 Catch
 {
 Write-host "Error while getting site users - "  $siteUrl " - "  $_.Exception.Message
 }
 Finally
 {  
 $site.RootWeb.Dispose()
 }  
 }  
 Write-host "================================ Completed ==========================================="
}
Catch
{
 Write-host "Error while getting sites from the sharepoint farm - " $_.Exception.Message  
}
 
Stop-Transcript

For all web applications including central admin Web App:

If you want to run the script for all web applications including central admin, then use below command in the script:

$sites = Get-SPWebApplication -IncludeCentralAdministration | Get-SPSite -Limit All | Select URL -ErrorAction Stop 

For all web applications excluding central admin Web App:

If you want to run the script for all web applications except central admin web application, then use below command in the script:

$sites = Get-SPWebApplication | Get-SPSite -Limit All | Select URL -ErrorAction Stop

For Single or Multiple site collections:

If you want to run the script for single or multiple site collections, then use below command in the script:

$sites="http://sharepoint/sites/site1","http://sharepoint/sites/site2" 

This script creates transcript file(.txt file) and it contains orphan users and site URLs details. We can use this as the report.