Dealing with Teams Guest Users During Tenant to Tenant Migrations

During Microsoft 365 tenant to tenant migrations, the question of Guest Accounts often comes up. How they are dealt with is critical as they are not internal users who can rely on our helpdesk for support. Because of this, a lot of organizations will choose to ignore Guest accounts and inform end users to re-invite the external users post-migration. This method works in theory but in practice, can cause frustration to end users who already have to adapt to a lot of change. In this post, I’ll go through the process I use during migrations to bring over Guest Users in the most seamless way possible.

High-Level Process

Before we get into the weeds, I’ll outline the high-level process we can follow to bring across Teams Guests between tenancies:

  1. Capture Guest Accounts from the Source Tenancy
  2. Provision Guest Accounts in the Destination Tenancy (without sending invitations)
  3. (Optional) Map Guest Accounts between Tenancies for Membership Automation
  4. Assign Team membership in the Destination Tenancy
  5. Communicate the change to External Users Along with the Redemption URL

The trick here is to frontload the Team membership and access before communicating to external users. This can be done by provisioning Guest Accounts without sending the automatic invitations which usually go out. Then a more complete communication can be used (along with instructions) to inform Guest Users of the change and allow them to redeem their new invitation.

Capture Guest Accounts from the Source Tenancy

This is the easy part, to list the Guest Accounts that need to be moved, Connect to Azure AD PowerShell and run the below command to export all Guests along with their email address, display name and Object ID.

Get-AzureADUser -Filter "userType eq 'Guest'" -All $true | select Displayname, Mail, ObjectID | Export-Csv SourceGuests.csv -NoTypeInformation 

Now you should have a CSV file containing the information needed to create the Guest Accounts in the target tenancy.

Provision Guest Accounts in the Destination Tenancy

With the list of accounts in a CSV, we can provision the using Graph API into the new tenant. The important step is that we don’t send out the default Microsoft email at this point as we don’t want external users to receive an unexpected invitation.

This can be done using a script I have shared previously here: Creating Custom B2B Guest User Invitations with Graph API (

Follow the steps in that article to set up the script and make sure to use the CSV that was exported previously as the input file. The script can be run in a loop like in the below example to provision all the accounts:

##Import a CSV with the following headers “Displayname”,”Mail”,”Message”
$CSV = Import-Csv SourceUsers.csv
$RedirectURL = “<Target Tenant ID>”
##Loop through CSV and create guests##
Foreach($user in $csv){
.\graph-CreateGuestUserInvitation.ps1 -UserDisplayName $User.DisplayName -UserEmail $User.Mail -ClientSecret $clientSecret -TenantID $tenantID -ClientID $clientID -SendInvite $false -RedirectURI $RedirectURI

Note: Add the Tenant ID of the destination tenant to the Redirect URL (Line 3) above. This URL will redirect Guests directly to your Teams instance after they redeem the invitation.

When the script runs, all of the Guests should have accounts in the destination tenancy but will not have received an invitation yet. The script will also output a CSV with the Invitation URLs for each user which can be used to send the invitations later. The file should look similar to Figure 1 below.

Figure 1: Guest Invitation Script Output File Example

(Optional) Map Guest Accounts Between Tenancies for Membership Automation

If there are not many Guest Accounts, they can be added manually to the correct Teams. If there are a large amount, I recommend creating a mapping file and scripting the addition of membership. If you want to automate the process, you’ll need to create a mapping file, if not, skip this step.

With the Guests created in the target, export the Guest Account information from the destination tenancy using the same command as you didn for the source:

Get-AzureADUser -Filter "userType eq 'Guest'" -All $true | select Displayname, Mail, ObjectID | Export-Csv TargetGuests.csv -NoTypeInformation 

With both the TargetGuests.csv and SourceGuests.csv files open, use Excel to match the Object IDs into a single CSV similar to the one shown in Figure 2.

Figure 2: Mapping file matching Source Tenant ID to Target Tenant ID for each account.

Assign Team membership in the Destination Tenancy

If you chose to manually add guests to Teams, you can go ahead and do this now, if you have a lot of Teams / Private Channels, then use the script I posted here to map membership from source tenant to target. This script can be run individually for each Team or as part of a loop to migrate multiple Teams at once. If using a loop, make sure to import a CSV of Teams to use similar to the example below:

##Import list of Teams to process
$csv = import-csv "C:\temp\Teamslist.csv"

##Loop through Teams
foreach($Team in $csv){

##Refresh Delegated Token
$token = get-msaltoken -ClientId $TargetclientID -TenantId $TargettenantID -Silent

##Nullify variables
$sourceteam = $null
$targetTeam = $null

##Run Script
 .\graph-Teams-Migration-Script.ps1 -SorceTeamObjectID $Team.SourceTeamID -SourceClientSecret $SourceclientSecret -SourceClientID $SourceclientID -SourceTenantID $SourcetenantID  -TargetClientSecret $TargetclientSecret -TargetClientID $TargetclientID -TargetTenantID $TargettenantID -TargetTeamObjectID $Team.TargetTeamID -MappingFile C:\temp\Mappingfile.csv -TargetToken $TargetToken.accesstoken

Communicate the change to External Users Along with the Redemption URL

With everything in place for the Guest Users, we can now send out the Redemption URL we collected earlier when creating the accounts, along with instructions and context. This can be done with a simple mail merge and provide a lot more information than the generic Microsoft email. My favourite piece of this process is that because we set the redirection URL to point to our Team instance, the external user is brought straight into Teams and access is all in place ahead of time, helping to create a simple user experience.


While there is no real “Migration” for Guest users in Azure AD, the method described here, in my opinion, is the most user friendly and non-disruptive way to bring Guest Accounts along the Tenant to Tenant migration journey.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s