SharePoint Online: Find and Delete Orphaned Users using PowerShell

find and delete orphaned users in sharepoint online

What are “Orphaned Users” in SharePoint Online?

In short, orphaned users are those who were deleted from the authentication provider (such as removed from Active Directory when the user leaves the organization) and still continue to exist in SharePoint Online sites! Scanning each user in the SharePoint Online site collection for orphaned users could take days to complete! Since, Here is my PowerShell script to search for orphan users and delete them.

Pr-Requisites: Before using this script, you need to have SharePoint Online Management Shell (https://www.microsoft.com/en-us/download/details.aspx?id=35588) and Azure Active Directory Module (https://technet.microsoft.com/en-us/library/dn975125.aspx) installed on your machine!

Find Orphan Users in SharePoint Online using PowerShell:

This script scans every user from the given site collection URL and exports the list of orphaned users to a CSV file.

#Import SharePoint Online and Azure Online modules
Import-Module Microsoft.Online.SharePoint.Powershell
Import-Module MSOnline

Function Generate-OrphanedUsersReport ()
{
param
    (
        [Parameter(Mandatory=$true)] [string] $AdminURL,
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ReportOutput        
    )
Try {
    #Get Credentials to connect
    $Cred = Get-Credential

    #Connect to SharePoint and Azure AD
    Connect-MsolService -Credential $cred
    Connect-SPOService -Url $AdminURL -Credential $Cred

    #Function to check if a user account exists
    Function Check-UserExists()
    {
        Param( [Parameter(Mandatory=$true)] [string]$UserID )
    
        $User=Get-Msoluser -UserPrincipalName $UserID -Erroraction SilentlyContinue
        if ($User -ne $null)
        {
            Return $True
        }
        else
        {
            Return $false
        }
    }
    $OrphanedUsers = @()

    #Get all users of a given SharePoint Online site collection
    $AllUsers = Get-SPOUser $SiteURL -Limit ALL

    Foreach($User in $AllUsers)
    {
        #Exclude Built-in User Accounts and Security Groups 
        if(($User.DisplayName.ToLower() -ne "nt authority\authenticated users") -and ($User.LoginName.ToLower() -ne "sharepoint\system") -and 
        ($User.DisplayName.ToLower() -ne "sharepoint app") -and ($user.IsGroup -eq $false ) -and(-not $user.DisplayName.ToLower().Contains("_spocache")) -and 
        (-not $user.DisplayName.ToLower().Contains("_spocrawl")) -and ($User.DisplayName.ToLower() -ne "sharepoint service administrator") -and 
        ($User.DisplayName.ToLower() -ne "guest contributor") -and ($User.DisplayName.ToLower() -ne "everyone except external users")-and ($User.DisplayName.ToLower() -ne "company administrator"))
        {
            Write-host "Checking user $($user.DisplayName)" -f Yellow
            #Check if user exists
            if((Check-UserExists $User.LoginName) -eq $False)
            {
                Write-Host "User Doesn't Exists: $($user.DisplayName) - $($User.LoginName)" -f Red

                #Send the Result to CSV 
                $Result = new-object PSObject
                $Result| add-member -membertype NoteProperty -name "LoginName" -Value $User.LoginName
                $Result | add-member -membertype NoteProperty -name "DisplayName" -Value $User.DisplayName
                $OrphanedUsers += $Result
            }
        }
    }
    #Export results to CSV
    $OrphanedUsers | Export-csv $ReportOutput -notypeinformation

        Write-host "Orphan Users Report Generated to $ReportOutput" -f Green
   }

    Catch {
    write-host -f Red "Error Deleting Unique Permissions!" $_.Exception.Message
    }
}

#Config Parameters
$AdminURL ="https://crescent-admin.sharepoint.com"
$SiteURL = "https://crescent.sharepoint.com"
$ReportOutput="C:\Temp\OrphanUsers.csv"

#Call the function to find and generate orphaned users report
Generate-OrphanedUsersReport -AdminURL $AdminURL -SiteURL $SiteURL -ReportOutput $ReportOutput

This script checks each user of the given site collection and generates a CSV file:

powershell to find orphaned users in sharepoint online
Be sure the CSV generated doesn’t include any built-in user accounts and groups, prior providing the CSV file as an input to the next step of removing orphan users!

How to Delete Orphan Users from SharePoint Online with PowerShell:

While it is possible to remove each user from the SharePoint Online site collection individually, it becomes cumbersome when we have a large number of orphan users to remove! Here is the PowerShell script to read orphan users from the CSV file generated in the previous step and remove them all in one go!

#Import SharePoint Online module
Import-Module Microsoft.Online.SharePoint.Powershell

Function Remove-OrphanedUsers ()
{
param
    (
        [Parameter(Mandatory=$true)] [string] $AdminURL,
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ReportInput        
    )
    Try {
        #Get Credentials to connect
        $Cred = Get-Credential
   
        #Connect to SharePoint Online
        Connect-SPOService -Url $AdminURL -Credential $Cred

        #Get the Data from CSV and Add to SharePoint List
        $OrphanUsers = Import-Csv $ReportInput
        Foreach ($Row in $OrphanUsers) 
        {
            #Remove user from site
            Remove-SPOUser -Site $SiteURL -LoginName $Row.LoginName
            Write-host "Removed the Orphaned User $($Row.DisplayName) from $($SiteURL)"   
        }
            Write-host "Orphaned Users Removed from SharePoint Online Site!"
       }
    Catch {
    write-host -f Red "Error Deleting Orphan Users!" $_.Exception.Message
    }
}

#Config Parameters
$AdminURL ="https://crescent-admin.sharepoint.com"
$SiteURL = "https://crescent.sharepoint.com"
$ReportInput="C:\Temp\OrphanUsers.csv"

#Call the function to Remove Orphaned users
Remove-OrphanedUsers -AdminURL $AdminURL -SiteURL $SiteURL -ReportInput $ReportInput

You can use these functions to find and/or remove orphaned users from all site collections. Just add:

Get-SPOSite -Limit all | ForEach-Object { 
  #Call the function to find and generate orphaned users report
  Generate-OrphanedUsersReport -AdminURL $AdminURL -SiteURL $_.Url -ReportOutput $ReportOutput
}

Remove orphaned users from SharePoint Online to maintain good governance and security practices.

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two-decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. He has held various positions including SharePoint Architect, Administrator, Developer and consultant, has helped many organizations to implement and optimize SharePoint solutions. Known for his deep technical expertise, He's passionate about sharing the knowledge and insights to help others, through the real-world articles!

25 thoughts on “SharePoint Online: Find and Delete Orphaned Users using PowerShell

  • Hi,

    The “find” script seems to be also including active users that are still in the AD, along with deleted users.

    Do you know what could cause that?

    Reply
  • Does this script identifies the Inactive users also!! Or only deleted users!

    Reply
  • Hi
    Do you have a PS script to remove all deleted groups?

    Reply
  • Nice article! Have you thought about making a version of the script that would use App permissions? Is it possible?

    Reply
  • Nice article! Have you thought about making a version of the script that would use App permissions? Is it possible?

    Reply
  • Is there a way we can provide input file to get report on orphan users?

    Reply
  • Is there a way to replace the orphaned user with active user instead of deletion at library level?

    Reply
  • Can we run this powershell as job on daily basis. Where can we keep and how can we run it daily automatically?

    Reply
  • Hi, the remove script doesn’t work for me
    I get this error=
    Error Deleting Orphan Users! Cannot bind argument to parameter ‘LoginName’ because it is null.

    Any idea?

    Reply
    • The “LoginName” column from the CSV file is populated from the first script in this article. Make sure you have the correct Login Names populated!

      Reply
    • The CSV file was correctly generated by the first script.
      It looks like this
      LoginName,”DisplayName”
      firstname.lastname@ourdomain.be,”firstname lastname”

      Looks fine to me, don’t understand why I’m getting this error

      Reply
      • Even I am facing the same issue!

        Reply
  • great script, is there any way to do the same process but with PnP? Thanks.

    Reply
    • There are not cmdlets available to find and remove orphaned users. But you can use “Remove-PnPUser” to remove any user from site collection.

      Reply
    • Thanks Salaudeen…..

      Reply
  • Thanks for your help. Here, as per your script for multiple site collection it’s keep on asking user ID and pwd for each site.
    Get-SPOSite -Limit all | ForEach-Object {
    #Call the function to find and generate orphaned users report
    Generate-OrphanedUsersReport -AdminURL $AdminURL -SiteURL $_.Url -ReportOutput $ReportOutput
    }

    However, we have more than 2000+ site collections. so it’s difficult to identify the orphaned users for 2000+ sites.Here, I have modified script but it’s not working .Please refer the below.
    #Import SharePoint Online and Azure Online modules
    Import-Module Microsoft.Online.SharePoint.Powershell
    Import-Module MSOnline

    Function Generate-OrphanedUsersReport ()
    {
    param
    (
    [Parameter(Mandatory=$true)] [string] $AdminURL,
    #[Parameter(Mandatory=$true)] [string] $SiteURL,
    [Parameter(Mandatory=$true)] [string] $ReportOutput
    )
    Try {
    #Get Credentials to connect
    $Cred = Get-Credential

    #Connect to SharePoint and Azure AD
    Connect-MsolService -Credential $cred
    Connect-SPOService -Url $AdminURL -Credential $Cred

    #Function to check if a user account exists
    Function Check-UserExists()
    {
    Param( [Parameter(Mandatory=$true)] [string]$UserID )

    $User=Get-Msoluser -UserPrincipalName $UserID -Erroraction SilentlyContinue
    if ($User -ne $null)
    {
    Return $True
    }
    else
    {
    Return $false
    }
    }
    $OrphanedUsers = @()
    #Create a Txt File with multiple Site URL’s
    $SiteURLs= Get-Content “E:Siteurl.txt”

    Foreach($SiteURL in $ SiteURLs)
    {
    #Get all users of a given SharePoint Online site collection
    $AllUsers = Get-SPOUser $SiteURL -Limit ALL

    Foreach($User in $AllUsers)
    {
    #Exclude Built-in User Accounts and Security Groups
    if(($User.DisplayName.ToLower() -ne “nt authorityauthenticated users”) -and ($User.LoginName.ToLower() -ne “sharepointsystem”) -and
    ($User.DisplayName.ToLower() -ne “sharepoint app”) -and ($user.IsGroup -eq $false ) -and(-not $user.DisplayName.ToLower().Contains(“_spocache”)) -and
    (-not $user.DisplayName.ToLower().Contains(“_spocrawl”)) -and ($User.DisplayName.ToLower() -ne “sharepoint service administrator”) -and
    ($User.DisplayName.ToLower() -ne “guest contributor”) -and ($User.DisplayName.ToLower() -ne “everyone except external users”)-and ($User.DisplayName.ToLower() -ne “company administrator”))
    {
    Write-host “Checking user $($user.DisplayName)” -f Yellow
    #Check if user exists
    if((Check-UserExists $User.LoginName) -eq $False)
    {
    Write-Host “User Doesn’t Exists: $($user.DisplayName) – $($User.LoginName)” -f Red

    #Send the Result to CSV
    $Result = new-object PSObject
    $Result| add-member -membertype NoteProperty -name “LoginName” -Value $User.LoginName
    $Result | add-member -membertype NoteProperty -name “DisplayName” -Value $User.DisplayName
    $OrphanedUsers += $Result
    }
    }
    }
    }
    #Export results to CSV
    $OrphanedUsers | Export-csv $ReportOutput -notypeinformation

    Write-host “Orphan Users Report Generated to $ReportOutput” -f Green
    }

    Catch {
    write-host -f Red “Error Deleting Unique Permissions!” $_.Exception.Message
    }
    }

    #Config Parameters
    $AdminURL =”https://abcd-admin.sharepoint.com”
    $SiteURL = “https://abcd.sharepoint.com/sites/abcd1″
    $ReportOutput=”E:OrphanedUserslist/Testurlslist.csv”

    #Call the function to find and generate orphaned users report
    Generate-OrphanedUsersReport -AdminURL $AdminURL -SiteURL $SiteURL -ReportOutput $ReportOutput

    Reply
  • Hi , Please can you help em to delete the Orphaned users. I used above scripts i could able to get the list orphaned users . but while using delete the user as given below script i have error msg like “Error deleting unique permissions!Could not find file “C:\temp\one.csv”
    #Import SharePoint Online module
    Import-Module Microsoft.Online.SharePoint.Powershell

    Function Remove-OrphanedUsers ()
    {
    param
    (
    [Parameter(Mandatory=$true)] [string] $AdminURL,
    [Parameter(Mandatory=$true)] [string] $SiteURL,
    [Parameter(Mandatory=$true)] [string] $ReportInput
    )
    Try {
    #Get Credentials to connect
    $Cred = Get-Credential

    #Connect to SharePoint Online
    Connect-SPOService -Url $AdminURL -Credential $Cred

    #Get the Data from CSV and Add to SharePoint List
    $OrphanUsers = Import-Csv $ReportInput
    Foreach ($Row in $OrphanUsers)
    {
    #Remove user from site
    Remove-SPOUser -Site $SiteURL -LoginName $Row.LoginName
    Write-host “Removed the Orphaned User $($Row.DisplayName) from $($SiteURL)”
    }
    Write-host “Orphaned Users Removed from SharePoint Online Site!”
    }
    Catch {
    write-host -f Red “Error Deleting Unique Permissions!” $_.Exception.Message
    }
    }

    #Config Parameters
    $AdminURL =”https://xyz-admin.sharepoint.com”
    $SiteURL = “https://xyz.sharepoint.com/sites/dummysite”
    $ReportInput=”C:tempone12345678.csv”

    #Call the function to Remove Orphaned users
    Remove-OrphanedUsers -AdminURL $AdminURL -SiteURL $SiteURL -ReportInput $ReportInput

    Reply
    • As the Error message says: Could not find file “C:\temp\one.csv”, Make sure you have the one.CSV file at “C:\temp\one.csv” with all orphan users list.

      Reply
  • This is so great! One question: where do I add this line?
    Get-SPOSite -Limit all | ForEach-Object {
    #Call the function to find and generate orphaned users report
    Generate-OrphanedUsersReport -AdminURL $AdminURL -SiteURL $_.Url -ReportOutput $ReportOutput
    }

    Reply
    • I’m pretty sure that will just overwrite the csv file for each site collection?

      Thanks for the script Salaudeen, its great !

      Reply
    • Yes! Use: -Append switch in Export-CSV cmdlet.
      $OrphanedUsers | Export-csv $ReportOutput -append -notypeinformation

      Reply
  • Oh awesome! This is great information. Thanks much for sharing such an informative post about SharePoint Online. In addition, I really thank you for defining “Orphaned Users” in SharePoint Online and explaining on how to find and delete the orphaned users in SharePoint Online using PowerShell. Great help!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *