LAB: Migrate Office 365 synced users from one on-prem forest to another forest

This post is inspired from a forum tread I answered over at Technet. After clicking Submit I got the feeling that I didn’t have all the facts, and that I might miss some of the steps.

It all started as a quick write on how to handle an AD migration where dirsync is in use also. Well, it turns out that this is no quick post at all, and actually became a LAB guide instead. In addition, yes, my feeling telling me that I might did not get the reply 100% correct was confirmed. Especially the part on how matching the synched users after migration works.

Anyhow, I hope that you find it interesting, and could use it to do something productive some time.

– Thank you MVP Olav Tvedt for reviewing the post:

The case

There is harsh times in the business market and Contoso Ltd. and Fabricam, Inc. has decided to fuse their business. The decision makers have decided that all users from Contoso are to be migrated over to Fabricam, and the Contoso name is discontinued.

You are an administrator at Fabricam, Inc. and have been delegated the task to make this go as smooth as ever possible. While you are at it, you also decided to restructure Active Directory in the target domain, so everything gets a bit more logical.

Some details on Contoso

  • Forest root domain name is
  • All users and security groups are located in a OU named Organization\Users and Organization\Groups
  • The UPN suffix for the users are
  • Located in Oslo, Norway
  • WAAD Sync enabled for the Office 365 tenant.
  • Using Exchange and Lync. SharePoint is not in use

Some details on Fabricam

  • Forest root domain name is
  • All users and security groups are located in a OU named Domain Users and Domain Groups
  • The UPN suffix for the users are
  • Located in Stavanger, Norway

The new company structure

The companies are merged, but the locations is kept, so I decide to use a geographical OU structure in Active Directory Domain Services. The result is an AD implementation looking something like this.


All users from Contoso are signing in using their UPN. This is also implemented in Office 365. Their Office 365 tenant is named

After the migration, all users will sign inn using This means that the Office 365 UPN suffix needs to be changed after the migration.


For demonstrating this case, I created the following LAB on my computer using the power found in Hyper-V for Windows 8.1. I also registered for a 30 days free trial Office 365 subscription. As you learn later on, ADMT has not been released for Windows Server 2012/2012R2 yet, so the servers are running Windows Server 2008R2.


I also populated the Contoso domain with a few users that I then synched with Office 365 using WAAD Sync Tool. I did not care to crate groups, as this is simply a demonstration.

In this deployment I have used two subdomains from my own root domain.


These domains is used both on-premises and in the cloud. The on-premises domains could have been whatever I like, but to make it easier, I chose to use the public routable domain on both. The reason for this is

  1. To use a custom domain for Office 365, or any Microsoft Online Service for that mater, it requires a public routable domain.
  2. I do not need to add an alternative UPN for all the users on-premises

You can read more about the Domain requirements in the Office 365 Service description, and UPN requirements in the Prepare for directory synchronization document for Windows Azure Active Directory

How did I do it?

Well, first I quickly browsed trough these articles to understand the concept of how ADMT and DirSync work.

A quick overview of the tasks looks like this

  1. Plan for an Interforest Migration
  2. Prepare the two forests
  3. Disable and remove the old WAAD Sync from
  4. Migrate the users to the new domain
  5. Installing WAAD sync in the new domain
  6. Change the UPN suffix for the migrated user

First step: Planning and preparing for an Interforest Migration

In this demo we are doing an Interforest Migration. That means that we are migration from one AD Forest to another, but you probably knew that already. There is a nice checklist at TechNet ( that gives us a quick overview of what we are going to do. I advise you to read this thoroughly before you do it in a production environment. For the purpose of this demo, just rush through it.

Second step: Preparing the two forests

This step involves three sub steps.

  1. Restructure the OU structure in the Fabricam domain as planned.
  2. Add as alternative UPN
  3. Establishing the Required forest trusts
  4. Create and establish required accounts for migration
  5. Install ADMT on

Restructure AD

In this step I am going to implement the structure planed earlier. In my case this is no big deal, sense I only have few OUs to create. Anyhow, there is no fun in doing this from a MMC snapin, so I created a PowerShell script.

First, I crated a CSV file containing the OU structure that I wanted, and saved it as OUStructure.csv. It looked like this.


Then I created a PowerShell script looking like this, and saved it as CreateOUStructure.ps1

foreach ($NewOU in $(Import-Csv .\OUStructure.csv -Delimiter ";")) {
    New-ADOrganizationalUnit -Name $NewOU.Name -Path $NewOU.Path

Finally, I opened Active Directory Module for Windows Powershell. It’s located under Administrative Tools, and then I simply ran .\CreateOUStructure.ps1


After this I had a OU structure looking like this in ADUC


Add alternative UPN

Before I continued with the trust part, I added as an alternative UPN using the Active Directory Domain and Trust MMC snapin. Just to get some variation. I could also run this PowerShell command in the Fabricam domain.

Set-ADForest –Identitiy –UPNSuffixes @{Add=""}

Create forest trust

This step is outlined in the following TechNet article, and a deeper dive on trusts can be found here

I am setting up a two-way trust.

The first thing to do is to make sure network communication is up, and DNS is in place. Sense this is my LAB; my RRAS takes care of the networking part. My job is to configure the DNS server.

Note: If you need to configure your firewall, something you probably should need to do if this where a production environment, take a look at these two articles that describes the required settings.

I begin at condc01 in and open DNS Manager. There I make a Conditional Forwarder, pointing to

Then I did the same thing at fabdc01 in, except that the conditional forwarder was for and was pointing to

Then I test DNS lookup in both domains before continuing. If everything looks fine, I am good to go.

Next step is to create the trust itself. I did the whole process in once from fabdc01 in Fabricam.

I open Active Directory Domains and Trust, located under Administrative Tools. There, I right click, select Properties, and click the Trusts tab. Then I click New Trust…


A New Trust Wizard pops up. I click Next at the first page.

At the Trust Name page, I enter the name of the remote forest.


Sense I am in a lab with only one domain in each forest, the next step does not matter that much, so I just click Next here. The difference is that an External trust only trust the domains we specify. A Forest trust would trust any domain in the target forest.


The next window asks me to choose the direction of the trust. For the purpose of this demo, I just leave the defaults and create a Two-way trust. We create a two what trust because we want both forests to trust each other.


Now I am asked if I want to create the trust in both domains at once, or in this domain only. I choose Both this domain and the specified domain. This way, I save some time, sense this wizard automatically creates the trust in the other domain.


Then I am are asked for the User Name and Password for the remote domain. I just use the Domain Administrator account.


Next step is to set the scope of authentication. I simply go with the defaults here, and select Domain-wide authentication both from and from the local domain. This way I do not have to grant specific accounts access. And in this case, both domains are in the same Organization.


I am now ready to create the trust. Click Next to create it


And boom, the trust is in place. The last steps is to verify the trust. I get the option to do so at the next page.


I make sure to select Yes, confirm the outgoing trust, and click Next. This probably work. If not, take a look at this article over at TechNet


Next, I confirm the incoming trust, by selecting Yes, confirm the incoming trust and click Next.


This should also be a success, so now I can click Finish. For now, I just ignore the warning about SID filtering. I am going to let ADMT configure this for me the first time it runs.


Lest get to the next step, and configure some migration accounts.

Creating Migration Accounts

This part is described in this TechNet article

I open ADUC on condc01 (DC at our source domain) and add an account called res_migrator. I also add this account to the Domain Admins group.

Then sign in to the domain controller in the target domain. That would be fabdc01.

My res_migrator account need delegated access to the Oslo OU, as this is the destination for migrated users and groups.

I right click the Oslo OU, and click Delegate Control… I click Next on the Delegating of Control Wizard welcome page.

Then I add reg_migrator from the contoso domain, and click Next


On the Tasks to Delegate, I select

  • Create, delete, and manage user accounts
  • Create, delete and manage groups
  • Modify the membership of a group


On the Completing the Delegation of Control Wizard page, I click Finish.

Then, I right click the root domain, and select Delegate Control… I click Next on the Welcome page. I Add our res_migrator account and click Next. Now, at the Tasks to Delegate page, I select Create a custom task to delegate, and click Next. On the Active Directory Object Type, I leave the defaults to This folder, existing objects in this folder, and creation of new objects in this folder, and click Next.

On the Permissions page, I find and check Migrate SID history.


I click Next, and then Finish.

The last step in preparing the reg_migrator account is to sign in at the server that’s going to run ADMT and add reg_migrator as local administrator.

Installing ADMT

ADMT version 3.2, which is the newest one available today, requires at least an MS SQL Express instance as a prerequisite. Therefore, I begin with the installation of SQL Server. MS SQL Express 2008 is downloadable from Yea, I am not kidding. If you try to use R2 or newer, you get this error message during the ADMT installation.


Except that, the SQL installation is straightforward. I start the setup file, click New installation, and just goes with the defaults. I also add CONTOSO\res_migrator to the list of administrators for the instance. If you are unsure, take a look at this blog post from MSDN (2008R2 but the basics apply), or do a quick bing.

Then I go to and download the installer for ADMT. The steps for installing ADMT is described here

On the Welcome page, I click Next, Agree to the License Agreement, and choose not to join the CEIP. Then I just click Next.

At the Database Selection page, I type the SERVER\Instance name for the SQL server. It should be something like ADMT\SQLEXPRESS. Hit Next. The wizard tries to connect, and if successful, the installation starts.

When done, I am prompted to import data. I choose No, do not … and click Next. This creates a new empty database for us. After a few seconds, I am able to click Finish.

The final step is to enable migration of passwords. This step is described here

While still signed in to our ADMT migration server, I open a command prompt and type

admt key /option:create / /keyfile:"C:\Users\res_migrator\keyfile" /keypassword:pass@word1


Next step is to install PES on our source DC. I copy the key file and sign in to I store the key file somewhere logical, and then download and run PES from

On the Welcome page, I click Next, and accept the license.

On the Encryption File page, I locate the file you copied, and click Next.


When prompted for password for the encrypting key, I type the same password that I used when generating the encryption file.


I click Next when prompted if I am ready.

After a few seconds, a box asks me if this is going to run as Local System account or another log on account. I just leave the Local System account selected and click OK. Setup will now finish and I have to restart the domain controller. After restart, I start Password Export Server Service from Services under Administrative Tools.

To finish off, we need to enable Audit Account Management and Audit Directory Service Access on both domain controllers. The next steps is a copy/paste from this TechNet article

  1. Log on as an administrator to any domain controller in the target domain.
  2. Click Start, point to All Programs, point to Administrative Tools, and then click Group Policy Management.
  3. Navigate to the following node:
    Forest | Domains | Domain | Domain Controllers | Default Domain Controllers Policy
  4. Right-click Default Domain Controllers Policy and click Edit.
  5. In Group Policy Management Editor, in the console tree, navigate to the following node:

Computer Configuration | Policies | Windows Settings | Security Settings | Local Policies | Audit Policy

  1. In the details pane, right-click Audit account management, and then click Properties.
  2. Click Define these policy settings, and then click Success and Failure.
  3. Click Apply, and then click OK.
  4. In the details pane, right-click Audit directory service access and then click Properties.
  5. Click Define these policy settings and then click Success.
  6. Click Apply, and then click OK.
  7. If the changes need to be immediately reflected on the domain controller, open an elevated command prompt and type gpupdate /force.
  8. Repeat steps 1 through 12 in the source domain.

ADMT is now ready for migration jobs, so let us run a quick test.

I open Active Directory Users and Computers on condc01, and create a new OU named Test. In it, I create a user object named Test User. Then at fabdc01, I create new OU named Test. On the OU in, I also delegate the same permissions for CONTOSO\res_migrator as I did for the Oslo OU earlier.

Back at the ADMT server, I make sure that I am signed in as CONTOSO\res_migrator. I open Active Directory Migration Tool from the Administrator Tools menu.

Then I right click Active Directory Migration Tool, and select User Account Migration Wizard.


On the Welcome page, I click Next as usual.

On the Domain Selection page, I add as Source Domain and as Target Domain. Then I click Next.


On the User Selection Option page, I choose Select user from domain, and click Next.

Then on the User Selection page, I add the test user I just created.


Then I select the Target OU in fabricam.


I choose to Migrate password on the Password Options page.


On the Account Transition Options page, I make sure to check Migrate user SIDs to target domain. I leave the rest to its defaults.


Now I get an error, telling me that auditing is not enabled in the source domain, and if I want it corrected. Yes, I want to.


Then I am warned about another issue. The local group CONTOSO$$$ does not exists. Yes, I want it created.


On the User Account page, I add the credentials for CONTOSO\res_migrator, and click Next


On the User Options page, I leave the defaults, and click Next.

On the Object Property Exclusion page, I do now exclude anything. Just click Next.

On the Conflict Management page, I select Do not migrate source object is a conflict is detected in the target domain, and click Next.

Then, at the Completing the User Account Migration Wizard, I click Finish. A progress window opens, and when Status changes to Competed, I click Close.


Migration works, so I can move on.

Third step: Preparing Office 365 before user migration

When we migrate the users to the new forest, it is also a good idea to make sure that synchronization with Office 365 happens from the new forest.

A quick overview of the steps looks like this

  1. Disable and remove dirsync from Contoso
  2. “Reset” dirsync in Office 365

Why, do you say?

If not, we would just get many error messages from the synchronization service, because the ImmutableID will be changed, and synchronization will fail in the old domain.

By removing WAAD Sync Tool from the old domain, and reset Active Directory Synchronization in Office 365, our users become “In cloud” users. This way we could continue synchronizing them from the new domain, by changing the ImmutableID once the users have been migrated.

I sign in to CONDC01 and uninstall Windows Azure Active Directory Sync Tool.

After uninstalling WAAD Sync Tool, I sign in to Office 365 admin center, and open users and groups. There, I click Deactivate on Active Directory synchronization.


This could take up to 72 hours, but my experience is that it takes a few minutes. When Deactivation is done, I activate it again, so everything is ready when we are going to install WAAD Sync Tool again in fabricam.

Fourth step: Begin migration

We should be ready for migration now. I sign in to using CONTOSO\res_migrator, and start Active Directory Migration Tool from the Administrative Tools menu.

I use the same procedure as with the test migration. Just this time, I select all the users from\Organization\Users and put them into their Oslo\Users\Office365 in the fabricam domain. Then I start migration.

When migration is done, I need to install WAAD Sync Tool, and get stuff ready for migration.

I download WAAD Sync Tool, and install it on FABDC01 using the best practice documented here

After installation, and initial configuration, I do not start the synchronization. We are first going to configure it, so only our Office365 OUs are synced.

I open Explorer and browse to C:\Program Files\Windows Azure Active Directory Sync Tool\SYNCBUS\Synchronization Service\UIShell\ and open miisclient.exe

When Synchronization Service Manager starts, I click Management Agents, and goes to Properties on the Active Directory Connector


There, I click Configure Directory Partitions and then click Containers … further down on the page.


I enter the same administrator credentials as I used to configure WAAD Sync Tool.


Then I select only those containers having objects that we want to synchronize with Office 365.


Then I click OK, and OK again until I am back in the Synchronization Service Manager again.

Now, if WAAD Sync Tool should run, we would get an error, sense out ImmutableID in Office 365 no longer matches our on-premises ObjectGUID. We are going to solve this using PowerShell, but first I need to install the tools

The script I am using looks like this. It gets all users from Office 365, matches them with the on-prem users, and then writes back the updated ImmutableID.

# Import required PowerShell Modules
Import-Module ActiveDirectory
Import-Module MSOnline
# Sign in to Office 365
$Office365AdminCredentials = Get-Credential
Connect-MsolService -Credential $Office365AdminCredentials
# Get all Office 365 users
$MsolUsers = Get-MsolUser
Foreach ($MsolUser in $MsolUsers) {
    # Test that the user on prem match the online user using the UPN
    If ($OnPremMatchingUser = Get-ADUser -Filter * | where {$_.UserPrincipalName  -eq $MsolUser.UserPrincipalName})
        # Fetch the ObjectGUID from the on-prem user as a byte array
        $ObjectGUID = $OnPremMatchingUser.ObjectGUID.toByteArray()
        # Convert it to a ImmutableID
        $NewImmutableID = [system.convert]::ToBase64String($ObjectGUID)
        Write-Host "Changing ImmutableID for Msol User" $MsolUser.UserPrincipalNAme
        Write-Host "- Old ImmutableID was" $MsolUser.ImmutableID
        Write-Host "- New ImmutableID is" $NewImmutableID
        Set-MsolUser -UserPrincipalName $OnPremMatchingUser.UserPrincipalName -ImmutableID $NewImmutableID

Now, it’s time to do the first sync from the new AD. I start PowerShell as an Administrator and open C:\Program Files\Windows Azure Active Directory Sync\DirSyncConfigShell.psc1

Then I run the command Start-OnlineCoexistenceSync

If you open Synchronization Service Manager and watches the Operations tab, you can see that the sync runs, and you should get an Operation saying that the Windows Azure Active Directory Connector with profile Export was a success.


Back in Office 365 admin center you can see that the users are no more In Cloud users, but Synced with Active Directory.

Fifth step: Enable new UPN for the users

My users are synching with Office 365, and everybody is happy. Except the branding department. All users from Contoso still uses their old UPN, both for sign on and as SMTP address suffix.

To solve this, I first add as a domain to our Office 365 subscription. After the domain has been validated, there is three steps to go through.

  1. Update the On-Prem UPN and e-mail address
  2. Update the Office 365 UPN
  3. Run DirSync

Of course we are going to use PowerShell to do this. Anything else would just be too time consuming.

Let me start with the on-premises accounts, and then the Office 365 accounts. Sign in to a computer having both the ActiveDirectory and MSOnline module for PowerShell installed, and run this script.

Import-Module ActiveDirectory
Import-Module MSOnline

Get-ADUser -Filter {UserPrincipalName -like "*"} | foreach {
    Set-ADUser $_ -UserPrincipalName $_.UserPrincipalName.Replace("","") -EmailAddress $_.UserPrincipalName.Replace("","")

$MsolCredentials = Get-Credential
Connect-MsolService $MsolCredentials

Get-MsolUser -DomainName "" | foreach {
    Set-MsolUserPrincipalName -UserPrincipalName $_.UserPrincipalName -NewUserPrincipalName $_.UserPrincipalName.Replace("","")

We are done, case closed 🙂


  1. Just a quick Question? Incase if an object is already in sync with office365 ( Mailbox enabled)which is from DomainA and if i Migrate the User to DomainB in the same Forest. Does it have any impact ?

  2. Hi.

    Nice article and great info.

    We are currently looking at a scenario where we have to do this. Have you ever tested this when the users have mailboxes in 365 that where migrated in hybrid from the source forest?

    I suppose we have to copy som exchange related attributes to the target forest before reconfiguring ad-connect.

    Also what happens with groups, do you know if they will be able to softmatch in AD-connect?

    1. Hi Endre! Sorry for the late reply.

      Haven’t tried this with groups or Exchange Hybrid Environment, but your anticipation makes sense.
      Did you ever get to try it?


  3. Is it possible to do this in batches? I’d like to stop syncing a few users at a time to make sure there’s as little disruption as possible.

    1. Hi Ryan,

      If you use the “Multiple forests, single Azure AD tenant” scenario for Azure AD Connect, then it should be possible to do it in batches.
      The scope of this lab on the other hand would not work, as you need a way to also move the ImmutableID to the new forrest. Employee ID or something

      Link to the Azure AD Connect scenario mentioned

      1. I’m not sure I understand. The goal is to go from 2 existing domains to one existing. Using multiple forests, one single Azure tenant would function but the idea is to get to one forest.

        Once a user is migrated to the target domain, they still exist in the source domain and have a remote user exchange mailbox. Do you just stop syncing them in the source domain and then change their ObjectGUID in the target?

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 )

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