This blog post has all come about as the client I was working for was having problems sharing documents in SharePoint with some external users. It turned out that the user was already in Azure AD as a Contact which is part of Exchange. This meant when an internal person attempted to share/Invite into SharePoint/MSTeams it all appeared to work correctly for the external user, but sometimes it didn’t. When looking at external users through the Admin portal, this external user was showing, but their email address was blank. After speaking with Microsoft, it turns out, because the email address was already found within the tenancy, it creates a unique violation when adding the external user to the Active Directory.
I have been working with Microsoft support regarding this, and the resolution was that this is as design!!??! Only by feeding back on the Office 365 uservoice this issue “might” looked at and fixed. See resolution notes below:
Symptom:
When you invite external users who exist as contacts in your environment, their email does not get populated in their guest user ID which results in them not being able to login to your environment and access the shared data.
Cause:
The issue is coming from a conflict caused by the email address which is already populated for the mail contact.
Resolution:
This is behavior by design as all objects in Azure AD have to be unique.
You cannot have 2 objects with the same email address.When you invite one of your contacts to your content in O365, it actually creates a completely new guest user object in your environment and since the email address which is supposed to be populated in the email attribute is already in use by the contact, the email address does not get populated.
The only way to resolve this issue at the moment is to eliminate any conflicts that are in place, by removing the conflicting email contact and re-invite the user to your content.
More information:
The best thing I can offer to you is the following:Please go to our UserVoice portal where other people are facing the same behavior and up-vote it, comment and have the whole IT department do the same as well.
Allow a “Guest User” to be converted to a different account type
https://office365.uservoice.com/forums/273493-office-365-admin/suggestions/19966537-allow-a-guest-user-to-be-converted-to-a-differen
This led me to working on a process and script that would remove the users from everywhere.
Locations to remove the External User from:
- Contacts
- Azure AD Guest Users
- Azure AD Deleted Users
- All SharePoint Sites
- All SharePoint Hidden User lists
- SharePoint User Profile
Contacts
To remove the External User from the contacts you will need to use the MSOL PowerShell module.
$UserEmail = "<ExternalUserEmailAddress>" | |
Connect-MsolService | |
Get-MsolContact | ? EmailAddress -eq $UserEmail | Remove-MsolContact -Force |
Or you can manually do this by going to admin.microsoft.com and under Users -> Contacts select the user and click Delete contacts.
Azure AD
To remove the External User from Azure AD you will still require using the MSOL PowerShell module. In fact, this script and the above script could be merged.
$Environment = "<TenantName>" | |
$UserEmail = "<ExternalUserEmailAddress>" | |
Connect-MsolService | |
$externalConversionEmail = ($UserEmail -replace '@', '_') + "#EXT#@" + $Environment + ".onmicrosoft.com" | |
$FoundUser = Get-MsolUser | ? UserPrincipalName -eq $externalConversionEmail | |
if($FoundUser){ | |
Remove-MsolUser -UserPrincipalName $($FoundUser.UserPrincipalName) -Force | |
#To see All Deleted User Get-MsolUser -ReturnDeletedUsers | |
Remove-MsolUser -UserPrincipalName $($FoundUser.UserPrincipalName) -RemoveFromRecycelBin -Force | |
#To Remove All Deleted Users Get-MsolUsers -ReturnDeletedUsers | Remove-MsolUser -RemoveFromRecycleBin -Force | |
} |
To do this manually, in admin.microsoft.com under Users -> Guest Users, select the user and click delete.
Then go into Users -> Deleted users and remove them from there.
Remove from SharePoint
To remove from SharePoint, if you have a large tenancy and you don’t know all the places where the external user could have been shared with, then you will have to use the following script. This script will remove the external user from the SharePoint Site, ensure that they are removed from the User Information list, and then lastly it will clear the person from the SharePoint User Profile.
I discovered that if I didn’t remove them from the User Profile, when attempted to reshare a document with that user, the people picker would grab the internal userprincipalname (<ExternalUserEmail>#EXT#@<Tenant>.onmicrosoft.com) as the email address and then prevent me clicking the Sharing button. This is because the people picker uses Graph API /Me/People and grabs the value from there. Once removed from everywhere, including the User Profile this no longer happens.
The following script uses SPO PowerShell Module and you will need to connect first using Connect-SPOService. The account that you use, needs to be a SharePoint Global Administrator.
The script checks if it can find the ExternalUser, and if it can remove the user using Remove-SPOExternalUser.
Then it loops through every site collection and looks for the user using Get-SPOUser with the internal userprincipalname. If found it removes the user using Remove-SPOUser. Once it has looped through all SharePoint sites, it then checks the SharePoint User Profile and removes the user from UserProfile Remove-SPOUserProfile. This command will remove a user from the UserProfile if they in the “Active Profiles” or the “Profiles Missing from Import”
<# | |
.SYNOPSIS | |
Loops through the SharePoint sites of the tenant, looking for the external user and removing them. | |
You need to have already connected to the Tenant as a SharePoint Global Adminstrator using Connect-SPOService -url:https://<tenant>-admin.sharepoint.com | |
.EXAMPLE | |
.\Remove-ExternalUserFromTenant.ps1 -Environment:<tenant> -UserEmail:<externalEmailAddres> | |
#For Tenant called Dev34223 and external email address fred.bloggs@outlookdomain.com | |
.\Remove-ExternalUserFromTenant.ps1 -Environment:Dev34223 -UserEmail:fred.bloggs@outlookdomain.com | |
#> | |
[CmdletBinding(SupportsShouldProcess)] | |
param( | |
[Parameter(Mandatory)] | |
[string] | |
$Environment, | |
[Parameter(Mandatory)] | |
[string] | |
$UserEmail | |
) | |
Clear-Host | |
$sites = Get-SPOSite -Limit ALL | |
$externalConversionEmail = ($UserEmail -replace '@', '_') + "#EXT#@" + $Environment + ".onmicrosoft.com" | |
$ErrorActionPreference = 'Stop' | |
$InformationPreference = 'Continue' | |
Write-Information -MessageData "Get $UserEmail External User within SharePoint" | |
$ExtUser = Get-SPOExternalUser -Filter $UserEmail | |
if ($null -ne $ExtUser) { | |
Write-Information -MessageData "Remove $UserEmail within SharePoint" | |
Remove-SPOExternalUser -UniqueIDs @($ExtUser.UniqueId) -Confirm:$false | |
} | |
$found = $false | |
$Sites | ForEach-Object { | |
$site = $PSItem | |
$i = $i + 1 | |
try { | |
Get-SPOUser -site:$($site.Url) -LoginName:$externalConversionEmail | |
write-Information "Found user $UserEmail in site $($site.Title) Url:$($site.Url)" | |
Remove-SPOUser -site:$($site.Url) -LoginName:$externalConversionEmail | |
$found = $true; | |
} | |
catch { | |
#User not found. | |
} | |
Write-Progress -Activity "Removing User - $UserEmail" -Status "Progress:$($site.Url)" -PercentComplete ($i / $Sites.count * 100) | |
} | |
if ($found) { | |
Write-Information "User $UserEmail removed from SharePoint Sites" | |
} | |
else { | |
Write-Information "User $UserEmail wasn't found within SharePoint Sites" | |
} | |
Write-Information -MessageData "Remove $externalConversionEmail from SharePoint User profile" | |
try { | |
Remove-SPOUserProfile -LoginName $externalConversionEmail | |
} | |
catch { | |
Write-Information "Unable to find $externalConversionEmail in the user profiles." | |
} |
If the plan is to add the external person back into your tenant, once the script has run, you will need to wait at least a few hours (maybe leave it for a day to be sure) to ensure all back end processes of Microsoft have completed.
When you share a document/folder with the external user they will get the invited link and enter a code experience, this way they do not turn up inside you Azure AD. However, if you share a site with them, or add them to a MS Teams, they will appear in your Azure AD correctly.