Weekend Scripter: Use PowerShell to Migrate to Active Directory On-Premises

Summary: Microsoft PFE, Asia Gandecka, talks about using Windows PowerShell to migrate users from Windows Azure Active Directory to Active Directory on-premises.

Microsoft Scripting Guy, Ed Wilson, is here. Let’s welcome a new guest blogger, Asia Gandecka…

Photo of Asia Gandecka

I have been with Microsoft since 2011 working as a a premier field engineer. I support the SharePoint infrastructure, Office 365, and SharePoint Online. SharePoint and Windows PowerShell work closely together, but it wasn’t until Office 365 when I decided to take a stab at Windows PowerShell. I have found it very handy at allowing me to manage SharePoint and Office 365 in faster, simpler, and more robust ways. It’s my first time here, and I am excited to share with you some of my work. Have fun scripting!

When working with a customer, we got to a point where we wanted to move users from Office 365 in Windows Azure AD to Active Directory on-premises. We wanted to start using Windows Intune, which requires using Active Directory on-premises.

The big questions we had was, “How can we avoid duplicate UPNs?” in addition to making sure that the users' data in the cloud stayed as-is. In this scenario, users only utilized SharePoint Online, and they did not have Exchange Online set up. That did not allow the SMTP email addresses to match the user’s names.

So, is it possible to match the users? The quick answer is, “Yes!”

Those who have worked with Active Directory and the directory synchronization tool, DirSync, know already that this tool it is one way to sync from Active Directory on-premises to Windows Azure AD. In this scenario, I need the exact opposite. Yes, I still claim it is possible. Let me explain…

Every user has a unique identifier in Active Directory on-premises called ObjectGUID, which in Windows Azure AD is ImmutableId. It pretty much is the same thing, but it is coded differently. I look at it as the same word, but a different language.

When DirSync runs, it takes the user’s information—its ObjectGUID and their UPNs—and tries to move it to Windows Azure AD. If a UPN is already taken by an object in Windows Azure AD, you will receive the error message shown in the following image:

Image of error message

The Distinguished Name is our ImmutableId here.

This is the time to make the translation and prove to DirSync that ObjectGUID is in fact ImmutableId for the UPN that we are trying to synchronize.  

In this example, we have user AsiaK@onlineworld.co, and we will translate the ObjectGUID so that it is understood by DirSync.

     Note  If you are not running it on an Active Directory server you will need to import the Active Directory module on that
     computer. For instructions, read the following Hey, Scripting Guy! Blog posts:

You will also need to set up your computer for access to Windows Azure AD and download the Windows PowerShell module for it. For instructions, read Manage Windows Azure AD using Windows PowerShell.

We can start working with the script in Window PowerShell modules that are installed for Active Directory and Microsoft Online Services (MSOnline):

PS C:\> Import-Module ActiveDirectory

PS C:\> Import-Module MSOnline

Image of command

Then connect to Office 365:

PS C:\> Connect-MsolService

Image of menu

Next, I am assigning the user that I would like to fix. (Later I will show you how to automate this for more than one user.)

PS C:\> $FixUser = “AsiaK@onlineworld.co

Then I am getting the organizational unit (OU) that the user is in, in Active Directory on-premises.

PS C:\> $ou = "DC=contoso,DC=com"

Next, we need the Active Directory on-premises user information. We are getting the user based on their UPN and OU.

PS C:\> $ADUser = Get-ADUser -SearchBase $ou -Filter {userprincipalname -like $FixUser}

It is good to double-check that we got what we wanted. To verify, run:

PS C:\> $ADUser

We can see in the following image that our ObjectGUID looks different than the ImmutableId (Distinguished Name) that we found previously:

Image of command output

Let’s verify whether the user in the cloud has the ImmutableId set (this step is optional). Get-MsolUser will return all users from Windows Azure AD. To specifically check on AsiaK, we add –UserPrincianleName $FixUser. And I want to present the data in a table (FT) with only UserPrincipalName and the ImmutableId.

PS C:\>  Get-MsolUser -UserPrincipalName $FixUser | FT UserPrincipalName, ImmutableID 

Image of command output

As shown here, we do not have the ImmutableId set. Let’s fix that.

We take all we have in $ADUser, and by using pipe character ( | ), we can convert the ObjectGUID to ImmutableId based on what is stored in $ADUser. The [Convert]::ToBase64String($_.ObjectGUID.ToByteArray()) will do the conversion trick.

After that, we take all of that information and set the Windows Azure AD users ImmutableId accordingly. The script to do this is:

PS C:\>  $ADUser | ForEach-Object {

$immutableId = [Convert]::ToBase64String($_.ObjectGUID.ToByteArray());

Set-MsolUser -UserPrincipalName $_.UserPrincipalName -ImmutableId $immutableId;


To verify that we correctly got the user set, we can run the Get-MSolUser command again:

PS C:\>  Get-MsolUser -UserPrincipalName $FixUser | FT UserPrincipalName, ImmutableID 

Image of command output

We can now see that the ImmutableId matches the Distinguished Name from the error message. Now we can re-run DirSync, and the user will sync correctly.

If we would like to automate the process for all users we can make few small changes to the script, as shown here: 

#Connect to Office 365

PS C:\> Connect-MsolService

#specify UPN suffix from AD onprem. Change contoso.com to match your domain this way everyone under that domain will be synchronized.

 PS C:\> $upns = "*contoso.com"

#Set OU, change Contoso to match your local AD setup.

 PS C:\> $ou = "DC=contoso,DC=com"

# This will get all users under $OU where their UPN contains $upns (anything that matches *contoso.com).

 PS C:\> $Users = Get-ADUser -SearchBase $ou -Filter {userprincipalname -like $upns}

#Match all the users 

PS C:\> $Users | ForEach-Object {

                $immutableId = [Convert]::ToBase64String($_.ObjectGUID.ToByteArray());

                Set-MsolUser -UserPrincipalName $_.UserPrincipalName -ImmutableId $immutableId;


#Verify all users have been assigned the ImmutableId.

 PS C:\> Get-MsolUser | Format-Table UserPrincipalName, ImmutableID 


Thank you, Asia, for writing this blog and sharing your knowledge and time.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy