Configure Azure AD connect

Recently I was involved in a project where the customer was interested in syncing their on premise ADDS with Azure AD (AAD). However, the only problem was that the business had been using ADDS since NT version and had been using Office 365 since its early days. This early adoption of technology caused parallel independent environments. Luckily the environments were not that big initially and were manageable however, with the expansion during the years, management became a living nightmare. Both environments included the same users, however, the username were different, nicks were different, information/attributes were different as the update in each environment required manual updates. Not having the same or all the information at one place was causing a lot of management problems, and not to mention the fear of reconfiguring something unknown.

In this blog post I will describe the entire process of how we started, the phases it went through from A to Z, which tools were leveraged and what the end result became. Hopefully this post will help someone out there who might be in a similar situation. Mostly the customers you work with already have AAD sync, or you setup new environments hence this problem scenario is not relevant. However, based on my experience, the world is a scattered place and not all business all utilizing the latest and greatest technology. Nevertheless, lets start the first blogpost

Business goal

The aim of this project was to merge identities into uniform identities that should be able to be used in on-prem integrations as well as cloud based integrations. Acquisition of new products normally provides an option to integration with existing systems. Mostly the customers have a directory service being either Microsoft Active directory or now the new younger brother Azure Active directory.

Team members/project members

As this project was a result of an HR management system acquisition, IT and HR were the natural parts of the team. In addition to these departments senior management was involved as the changes caused by the project would impact all the employees either directly or indirectly. Time frame for the project was set to 7 months, this included the planning, preparations and the initial migration or merger of user identities.

Goal

Goal with the project was to provide users with a uniform user ID, having the same username and password on-prem as well as in Office 365.

Tools utilized

  1. Azure AD connect
  2. ADDS users and computers MMC
  3. Domain and trusts MMC
  4. Powershell with MSOL commmandlets
  5. Powershell with Exchange-Online commandlets
  6. Powershell with ADDS commandlet
  7. Office 365 administration centre
  8. Google to find a description of AAD connect error 0x8023134a

Project Phases

Phase 1:

User identity in Office 365 and on-prem ADDS user identity must have something in common. This is just to make sure that you have a unique key/value that can be utilized to update information in both directories. We chose to use the mail attribute aka email address as it was unique. However, the challenge was that not all users in ADDS had the email address attribute added to them, as the email was supposed to be provided by Exchange online. Luckily or unluckily we have no common attribute that could be utilized to match the identities. So the solution became to update almost 2000 user objects manually. Yes you read it right, 2000 users were updated by adding email addresses manually. We utilized the following Powershell script utilizing get-azureaduser to enlist all users and their email addresses from Azure AD.

Connect-AzureAD

$users = Get-AzureADUser 

foreach($user in $users)
{
$name = $user.displayname
$mail = $user.mail
    if(($mail -notmatch "onmicrosoft.com") -and ($mail -ne "") -and ($mail -ne " ") -and ($mail -ne $null)) 
        {
            Write-Host $name","$mail
        }
}

This produced an output which consisted of user display name and their email address. Afterwards, all users in ADDS were updated with their email address.

Phase 2

After the users were updated with email addresses, we had to update the remaining attributes on ADDS users identity as it will be used as master data during initial synchronization. During phase 2, the same script from phase 1 was utilized, however some changes was made to include relevant fields for example

  • Department, Title, City, Mobile etc.

To update the ADDS from AAD user object a new Powershell script was created. This script matched the users from both directories based on email address. The CSV file created from export was utilized to add/set attributes to user objects. We used functions, as this code is a part of a much bigger script, however, the relevant sections have been added below

Function createAADUsersCSV (){

Connect-AzureAD
$outfile = "C:\Users\XXXYYYZZZ\Desktop\aaduserslist.csv"
$aadUsers = Get-AzureADUser -All $true
$textToInsert = "aadmail,aadmobile,aaddepartment,aaddisplayname,aadgivenname,aadsurname,aadjobtitle,aadphysicaldeliveryofficename,aaduserprincipalname"

write-host $textToInsert -ForegroundColor Green #Heading to be inserted in CSV

New-Item -Path $outfile -Force
Add-Content -Path $outfile -Value $textToInsert -Force


foreach($aadUser in $aadUsers)
{
  $aadAccountEnabled =  $aadUser.AccountEnabled
  $aadDepartment = $aadUser.Department
  $aadDisplayName =$aadUser.DisplayName
  $aadGivenName = $aadUser.GivenName
  $aadSurname = $aadUser.Surname  
  $aadJobTitle = $aadUser.JobTitle
  $aadMail = $aadUser.Mail
  $aadMobile = $aadUser.Mobile
  $aadPhysicalDeliveryOfficeName = $aadUser.PhysicalDeliveryOfficeName
  $aadUserPrincipalName = $aadUser.UserPrincipalName

    if (($aadAccountEnabled -eq $true) -and ($aadMail -ne $null) -and ($aadMail -notmatch "onmicrosoft.com") -and ($aadMail -match "domain.com") -and ($aadJobTitle -notmatch "ServiceAccount"))
        {
        $textToInsert = "$aadMail,$aadMobile,$aadDepartment,$aadDisplayName,$aadGivenName,$aadSurname,$aadJobTitle,$aadUserPrincipalName"
        Add-Content -Path $outfile -Value $textToInsert -Force
        Write-Host "$aadMail,$aadMobile,$aadDepartment,$aadDisplayName,$aadGivenName,$aadSurname,$aadJobTitle,$aadUserPrincipalName" -ForegroundColor Yellow
        
        }

}

}

function updateADDSuserFromAAD-CSV()
{

$infile = "C:\Users\XXXYYYZZZ\Desktop\aaduserslist.csv"
$aadUsers =  import-csv -LiteralPath $infile -Delimiter "," -Encoding ASCII
$count = 0

    foreach($aadUser in $aadUsers)
        {
            $aadMail = $aadUser.aadmail
            $aadMobile =$aadUser.aadmobile
            $aadDepartment = $aadUser.aaddepartment
            $aadDisplayName = $aadUser.aaddisplayname
            $aadGivenName = $aadUser.aadgivenname
            $aadSurname = $aadUser.aadsurname
            $aadJobTitle = $aadUser.aadjobtitle
            $aadUserPrincipalName = $aadUser.aaduserprincipalname
            $aadCity = $aadUser.city
            $aadCompany = $aadUser.company
            $aadMobile = $aadUser.Mobile
            $aadEmpNo = $aadUser.employeenumber

            #######Write-Host "From AAD csv file contents  $aadMail" -ForegroundColor Green

            $admail = Get-ADUser -Filter {EmailAddress -eq $aadMail} -Properties mail | Select-Object mail
            $admail = $admail.mail
#           Write-Host $admail -ForegroundColor Magenta
            
                        
                if($admail -eq $aadMail)
                    {
                        #Get-ADUser -Filter {EmailAddress -eq $aadMail} -Properties CanonicalName,CN,Company,Country,countryCode,Department,Description,DisplayName,DistinguishedName,Division,EmailAddress,EmployeeID,EmployeeNumber,Enabled,GivenName,HomeDirectory,Initials,mail,Manager,MobilePhone,Name,Office,OfficePhone,Organization,OtherName,physicalDeliveryOfficeName,SamAccountName,sn,State,StreetAddress,Surname,Title,UserPrincipalName
                        $user = Get-ADUser -Filter {EmailAddress -eq $aadMail} -Properties * ####mail #Company,employeeNumber,sn, givenName, title, manager,department,accountExpires,wWWHomePage,physicalDeliveryOfficeName,info,mobile,initials,displayname,userprincipalname,homedirectory,homedrive,mail
                        $samAccountName = $user.samaccountname
                        Set-ADUser -Identity $samaccountname -City $aadCity -Company $aadCompany -Department $aadDepartment -MobilePhone $aadMobile -EmployeeNumber $aadEmployeenumber

                    }

                        
}
}

createAADUsersCSV #Call the function to create CSV file from Azure AD
updateADDSuserFromAAD-CSV # Update user attributes in ADDS to match AAD attributes

Phase 3

Now that all the users had been updated, we could start focusing on the next step which was to install and configure Azure AD connect. Pre-requisites for the tool was followed, however as we had a non-routeable domain we had to do something with that as well. Our ADDS domain has a suffix of ourDomain.local. In order to cope with this problem, we had to add a UPN suffix to our ADDS domain which is routeable. So we ended up adding it to domain and services MSC.

After adding the new UPN suffix, it had to be added to all the users. We chose to utilize Powershell to the rescue.

$Users = Get-ADUser -Filter * -SearchBase "OU=subOu,DC=intra,DC=domain,DC=local" -Properties * | Where-Object {$_.userprincipalname -match "@intra.domain.local"} 

$Limit = $Users.count
$Creds = Get-Credential -UserName "domain\administrator" -Message "Enter credentials"

for($i=0;$i -le $Limit;$i++)
    {
        Write-Host "Name:" $Users[$i].name "UPN:" $Users[$i].userprincipalname "SAM:" $Users[$i].samAccountName 
        $upn = $Users[$i].SamAccountName + "@domain.com"
        Set-ADUser $Users[$i] -UserPrincipalName $upn -Credential $Creds
    }

Installing Azure AD Connect

Azure AD connect was set up on a member server, as we do not mix server roles and do not want to install other software on domain controllers than what is necessary. The tool is set up with following configuration

AAD Connect

You should have MFA enabled for all users before you start synchronizing identities, reason being very simple, users might have very weak passwords for on-prem ADDS. When you synchronize the password hashes to Office 365 the passwords for email accounts will be no stronger than what you had on-prem. We configured MFA on all our user account. In addition to that, we also configured conditional access forcing use of MFA for all Office 365 products from all locations except from our office Public IPs.

Also beware of Anchor ID! It is used in AAD connect tool to map you on-prem user with online AAD user ID. If you previously have tried to configure AAD connect in any previous versions, without successfully implementing the tool or just were tested it, you should check the immuitable ID on AAD user objects. We ran into a problem where AAD connect was not able to synchronize users between the directories and we started to get error 0x8023134a in AAD connect.

connected data source error code 0x8023134a attributeValueMustBeUnique

Which indicates that some important value(like primary key/id) for the object in question is not unique. It took our engineers a couple of days to figure out what the back laying problem was and how it could be resolved. It turns out that 0x8023134a error within AAD connect was being caused by Anchor ID. When Azure AD connect is about to synchronize an on-prem ADDS object to AAD object it calculates the unique ID’s of both objects and connects them using anchor ID. Why the error 0x8023134a could not just describe this, is a mystery to me, as the description of 0x8023134a is somewhat misleading only stating an attribute value must be unique. Back to solving the problem:

To solve the problem, our team had to retrieve object Guid in base64 format and add this value to each AAD object’s attribute in the field called immutable ID. This again was done with the help of this powerful tool called Powershell.

Export Errors Overview

To retrieve the object ID along with something that can be mapped to AAD we used the mail attribute as it was unique for each user. Following command was run on a DC to generate a log file containing all users and their object IDs.

ldifde -f AD-Users.ldf -r “(objectclass=user)” -l “dn, cn, mail”

ldifde to solve 0x8023134a error

This produces the following output file

ldifde export to solve 0x8023134a error

The cn value “SGxxxxxxxx3LDuHN2aws=” is the value which must be added to user in AAD as an immutable ID. We had to navigate through the file and find relevant values for each user. This was done by utilizing a hashtable called $container in the script below. The values might slightly vary for your implementation depending on values you extracted using ldifde. The Poweshell script we used was as following

connect-AzureAD
$ADData = Get-Content -Path C:\Users\XXXYYYZZZ\Desktop\AD-users.ldf
$Counter = $ADData.count 
$hits = 0

$currentObjGuidIndex = 0
[array]$container = @()

for($i=0;$i -lt $Counter;$i++)
{
    $objGUID = $null
    $objUPN = $null
    $objMail = $null
    $value = $ADDATA[$i]

        $container += $value

        if (($value -match "mail" ) -and ($value -match "@domainaddress.com" ) ) 
        {
            $j = $i - 2 #ImmutableID
            #$k = $i - 1 #UPN
                    

                    $objMail = $value
                    $objMail = $objMail.split(":")
                    $objMail = $objMail[1].trim()
                    #Write-Host $objMail
                    $objGUID = $container[$j]
                    $objGUID = $objGUID.split(":")
                    $objGUID = $objGUID[2].trim()
                    #Write-Host $objGUID
                    

                    Write-Host "Line counter:$i,$value, ImmutableID:" $container[$j] -ForegroundColor Green
                    Write-Host $objGUID -ForegroundColor Yellow
                    Write-Host $objMail -ForegroundColor Magenta
                    Get-MsolUser -UserPrincipalName $objMail | fl -Property Userprincipalname,Immu*
                    
                    Set-MsolUser -UserPrincipalName $objMail -ImmutableId $objGUID
                    #Write-Host "Set-MsolUser -UserPrincipalName $objMail -ImmutableId $objGUID" -ForegroundColor Cyan
                    $hits = $hits +1
                    
            
        }
 
  }

  Write-Host "Updated for number of users:" $hits -ForegroundColor Yellow

Phase 4

During this phase we started to move our users to the OU which is synchronized with Azure AD. Before moving the users the following things must be verified for each user, as failing to verify the information prior to move will cause negative user experience in form of unavailable mail service, invalid user etc.

  1. User UPN must be set the routeable domain
  2. User email and aliases must be defined. These values must exist in local ADDS under the attribute called proxyaddresses. For primary address use SMTP, for aliases use smtp. SIP addresses are also added here. This should already be present as a result from adding information from phase 2. However, if this is not present, you must make sure that each user get these attributes defined. In the additional info section below, a script and tips have been provided to cope with this problem as well.
  3. User must be informed to use the new user ID in Office 365. The chances are quite high that use was previously using their email address to login to Office 365, however, from this point forward they must use their UPN.

Benefits of this approach

The main benefits that we have gained are

  1. More secure user ID, as the user login name to Office 365 is no longer the same as email address, we have observed that number of false login attempts have decrease from 450,000 to almost 2 thousand. We do not know what the normal values for these attempts are, but this certainly makes monitoring of user logins much easier as there are far less false positives.
  2. Single username and password are applicable everywhere, both on premises and in the cloud. We have started to use password write-back and users are allowed to reset their own passwords, reducing the need for support from IT.
  3. When UPN is utilized for login to domain machines, it further makes life easier for users. Currently we are testing SSO capabilities so that users can access their Office 365 directly without needing to provide username or passwords while on work.

Additional information

Azure AD connect performs Hard or soft match. Make sure you understand the sequence and difference between these before you start setting up Azure AD connect. If you make sure the UPN is correct, proxyaddresses have been added and that there are no duplicates you are good to go. Annoying errors like 0x8023134a can be avoided by having immutable id defined. Although this should be done automatically by AAD connect, however if it fails, it is a simple and quick fix. Make use of complex and long passwords when setting up AAD connect as you most probably will not be utilizing MFA for these accounts.

You can download IdFix Directory Synchronization Error Remediation Tool from Microsoft https://www.microsoft.com/en-us/download/confirmation.aspx?id=36832

further detailed description of how AAD connect matches users between ADD and ADDS is described at https://docs.microsoft.com/en-us/azure/active-directory/hybrid/tshoot-connect-sync-errors

If you have any comments, feel free to comment the post and I shall try to respond in a timely manner.

Bonus section

The following Powershell script was utilized to add aliases and email addresses to all users within our ADDS environment. You need to export all users and their email address along with aliases using the exchange online Powershell module. Afterwards the following script shows how these can be added to ADDS objects



$emailAddresses = Import-Csv -Path C:\Users\XXXYYYZZZ\Desktop\Email-AddressDetails-ASCII.csv
$users = Get-ADUser -Filter * -Properties mail
$creds = Get-Credential -Message "Username and password for ADDS" -UserName "domain\administrator"
$lineNumber = 0


#$bruker = Read-Host -Prompt "Enter email address to search"
[array]$tempArray = @()
$hash = @{}
[String]$textValue = ""

Foreach ($user in $users)
{
    $adMail = $user.mail
    if(($adMail -ne "") -and ($adMail -ne $null))
        {
        #write-host "Currently processing $adMail" -ForegroundColor Green 
                
                foreach($emailAddresse in $emailAddresses)
                {
                    $displayName = $emailAddresse.DisplayName
                    $emails = $emailAddresse.EmailAddresses
                    $primaryEmail = $emailAddresse.PrimarySmtpAddress
                    $recepientType = $emailAddresse.RecipientType
              
                    if($adMail -eq $primaryEmail)
                        {
                            
                            $Hash += @{$adMail = $emails }                            
                            

                        }

                }

        }
}

$i = 0

$userCount = 0
foreach($user in $users)
{
    $adMail = $user.mail
    if(($adMail -ne "") -and ($adMail -ne $null))
        {
            $userCount = $userCount + 1
            #Write-Host $adMail -ForegroundColor Yellow
            #Write-Host "Address count found:" $aliasCount -ForegroundColor Yellow
            #$hash["$adMail"]
            $alias = [string]$hash["$adMail"]
            $alias = $alias.Replace(" ", ",")
            $alias = $alias.split(",")
            $aliasCount = $alias.count
                if($aliasCount -ge 1) 
                    {
                        for($i=0;$i -lt $aliasCount;$i++)
                            {
                                if(($alias[$i] -match "smtp") -or ($alias[$i] -match "Smtp") -or ($alias[$i] -match "SMTP") -or ($alias[$i] -match "SIP") -and ($alias[$i] -notmatch "onmicrosoft.com") -and ($alias[$i] -notmatch "SPO:SPO"))
                                    {
                                    
                                                    $currentUser = Get-ADUser -Filter * -Properties * -SearchBase "OU=TargetOU,DC=intra,DC=Domain,DC=Local" | Where-Object { $_.mail -eq $adMail} #| Select-Object samaccountname,distinguishedName
                                                    $samaccountname = $currentUser.samaccountname
                                                    $dn = $currentUser.distinguishedName
                                                    
                                                    if ($dn -match "TargetOU")
                                                        {
                                                            Write-Host $dn -ForegroundColor Cyan
                                                            Write-Host "To be added for user:"$alias[$i] -ForegroundColor Cyan
                                                            write-host "Set-ADUser -Identity $samaccountname -add @{ProxyAddresses="$alias[$i]"}" -ForegroundColor Yellow
                                                            Set-ADUser -Identity $samaccountname -add @{ProxyAddresses=$alias[$i]} -Credential $creds
                                                        }


                                    }
                            }
                    }

        }
}

Write-Host "Total users updated" $userCount

Evaluation

We successfully managed to synchronize our user identities and currently are looking at other features that should be utilized. We are also considering the upgrade of user licences to Office 365 M3-M5 licences. The project was delivered within the time frame that was defined before the project start. An overall description of steps would be

  • Enable MFA for alle users
  • Identify which sources should be used as master directory
  • Decide wither to use hard og soft matching or a combination. (Soft matching can only be used once during the first synchronization)
  • Add something common between directories
  • Update the On-prem directory with latest information
  • Set up Azure AD connect
  • Perform a pilot on a subset of users
  • Mass implementation if pilot is successful

Terms and conditions apply for use of scripts and resources provided in this blog. The technologies mentioned are rightfully owned by their registered trademark owners. The scripts or resources shared in the post are property of our blogging team. Reuse is only allowed under certain conditions. There are some strict requirements for publishing the code on any other sites, these too are described under terms page. Unless otherwise specified, publishing of code from this blog on other internet sites is strictly forbidden.

2 Thoughts on “Configure Azure AD connect

  1. Very good blog post certainly helped us solve the problem that we were having with regards to AD sync not functioning with error code 0x8023134a

Leave a Reply

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