How to migrate from Pass-through Authentication to Password Hash Sync

…and replace the AD security functions that blocked you so far!

Christopher Brumm
11 min readSep 18, 2021

The migration from Active Directory Federation Services (ADFS) to Password Hash Sync (PHS) is well documented by Microsoft and in various blogs. Since there are also many good reasons for the ADFS replacement, it really makes sense that the focus is on this. Especially since the migration from Pass-through Authentication (PTA) is very simple in comparison.

However, a migration from PTA to PHS also offers some advantages and the previously existing limitations are largely no longer present. So it is worthwhile to start this migration to have the following advantages:

  1. Support for leaked credential detection and AAD Domain Services
  2. Full integration with AAD Connect Health
  3. AAD auth independent from availability of OnPrem environment

For the general procedure, the migration guide for ADFS to PHS (+Whitepaper) offers a lot of useful information that can also be used here.

Why was PTA chosen in the first place?

Before migrating something, it is always a good idea to find out why the decision was made at that time. In my experience (apart from gut feeling 😉) the main argument for PTA was usually the requirement to use AD security policies. The MS documentation says:

If you need to apply, user-level Active Directory security policies such as account expired, disabled account, password expired, account locked out, and sign-in hours on each user sign-in, Azure AD requires some on-premises components.

Now Microsoft has upgraded a bit in this field and with a little effort you can use many of the functions with PHS and additionally use the above mentioned advantages.

Which and how can the AD Security functions be replaced?

Before we look at the individual functions in detail, I would like to ask “Do you really need all of them? What were the reasons you introduced these features back then?”

Most institutions like NIST, UKs NCSC or the German BSI have e.g. changed their stance on periodic password changes, externals can now be conveniently onboarded as guests, and in AAD there are features like Access Packages and Access Reviews to manage accounts and permissions.

A: Account Lockout

Account Lockout was and is an effective feature in Active Directory to prevent Brute Force Attacks because you can throttle the login trials. If you have not yet configured a lockout policy, my recommendation is to do so and also implement Microsoft Defender for Identity to make these attacks more difficult and to detect them.

In Azure Active Directory there is also an Account Lockout Policy but there it is only one of the many tools to protect the identities. Azure MFA and Identity Protection are way more effective in preventing Brute Force Attacks and also other — meanwhile much more common — attacks like Password Spraying.

With PTA (as with ADFS) there is the requirement to align lockout policies, otherwise it is easy for AD accounts to be locked out externally by failed login attempts (by attackers). In simple terms, this means that it is necessary to configure a more restrictive policy on the AAD than on the AD. (Detailed description)

On the subject of account lockout, the migration fundamentally improves the situation, as it is now no longer necessary to align the policies in AD and AAD to prevent AD accounts from being locked out externally.

So if you have a strict policy configured here it can be relaxed a bit — in my opinion there are much more effective measures in AAD to protect the accounts than account lockout.

B: Logon hours

The logon hour feature allows logons only at certain times of the week. This can be done either to increase security or, for example, to implement labour health and safety regulations. An example of both is to enforce that employees can only log on during their working hours.

While I see much better defence methods for security (Azure MFA, Password Protection, Microsoft Defender for Identity,…) the regulations issue can probably only be solved organisationally or maybe an approach like described here can work (fortunately I never had to implement that so far).

C: Account Expiration

For this part, Microsoft only points out that it would be useful to implement a PowerShell script that disables accounts that are expired. I have written a simple script (with lots of stolen snippets 🙃) to do that job which can run as a scheduled task in your AD.

To get a first idea how many user are affected in which locations just use this:

get-aduser -filter * -properties Name, PasswordNeverExpires, CN| Where-Object {$_.PasswordNeverExpires -and $_.Enabled} `
| Select-Object @{Label='ParentContainer';Expression={$_.Distinguishedname -replace "CN=$($,"}} `
| Group-Object -Property ParentContainer `
| Select-Object Name,Count `
| Out-GridView

Alternatively, of course, it may make sense to adapt the process and use access reviews in the future, for example.

A short excursion: You should take the opportunity to check whether your expired/disabled users might still be consuming licenses. AAD does not know expired users and disabled users do not automatically lose their licenses. A possible approach if you use Group Based Licensing (👍) would be to extend my script to remove all relevant groups…

D: Password Expiration

After switching to PHS, we no longer have a direct connection between the two directories. Now it is “just synchronized” and the authentication on the AAD is completely independent of the AD.

The basic problem with Password Expiration is very well described by Microsoft:

If a user is in the scope of password hash synchronization, by default the cloud account password is set to Never Expire. You can continue to sign in to your cloud services by using a synchronized password that is expired in your on-premises environment. Your cloud password is updated the next time you change the password in the on-premises environment.

The solution for the problem is then also described directly at the same point. However, since this solution has only been available since the end of 2019, many may have opted for PTA at that time.

To get the same function regarding password expiration with PHS you need

  • same password policies in AD and AAD (default 90 days)
  • Password Writeback to catch situations where the user is prompted by AAD to change the password.

Regarding a migration from PTA to PHS it is very useful to implement this before the first synchronization of the password hashes, otherwise a change cycle has to be waited until the adaptation takes effect.

In the planning it is very important to note that the AD flag “Password never expires” is not synchronized and has no effect in the AAD.

This means that if you synchronize service or functional users that have this flag set, you need to create a solution for these accounts. My first advice in this case is to check if these accounts need to be synced at all or can be taken out of sync. To check this, a script from Daniel Aldén has proven itself to me. I only modified it a bit to filter for the prefix SVC.

Your options for the rest of the service users are:

  • change your approach on periodic password changes and skip this topic (my favorite 😍).
  • create a script to find the users with the flag and change the password policy in AAD to never expire. Here is a very simple snippet:
Get-Content ServiceUser.txt | foreach { Set-AzureADUser -ObjectID <User Object ID> -PasswordPolicies "DisablePasswordExpiration"

If you’ve decided to keep the periodic change and after you took care for your service / function users you can changes the default behavior for synchronized users with the following CMDlet:

Set-MsolDirSyncFeature -Feature EnforceCloudPasswordPolicyForPasswordSyncedUsers

The next time the password hash is changed, the DisablePasswordExpiration attribute is automatically removed and the default policy takes effect. In our migration this should be done before you enable PHS.

How do I proceed reasonably with the migration?

As always with identity migrations, it makes sense to be well prepared and to deal with all topics to the extent that you understand exactly how the current and future solution works. A cut-over plan including rollback is also recommended.

Step 1: Preparation

This is the most important step — take your time for it!

Take care for the AD Security Features you want to replace

As described above, PTA may have some AD security features in use that cannot be mapped 1:1 in AAD or require additional preparations. It is important to have made decisions and preparations for these topics before switching on PHS.

Extend Permissions of the AADC Account in AD

Azure AD Connect will need additional permissions for enabling PHS and Password-Writeback. I’ve made very good experiences with the module shipped with AADC . If you’re not familiar with the module see Samis Blog on the topic:

Here is my script for granting the permissions:

Add-WindowsFeature RSAT-AD-PowerShell
Add-WindowsFeature RSAT-ADDS-Tools
Import-module ActiveDirectory
Import-Module "C:\Program Files\Microsoft Azure Active Directory Connect\AdSyncConfig\AdSyncConfig.psm1"
# Vars
$accountName = "ADDSConnectuser"
$ForestDN = "OU=xxx,DC=xxx,DC=xxx"
$domain = (Get-ADDomain).Forest
#Grant Permissions for PHS (Domain Admin needed)
Set-ADSyncPasswordHashSyncPermissions -ADConnectorAccountName $accountName -ADConnectorAccountDomain $domain
#Grant Permissions for PW Writeback
Set-ADSyncPasswordWritebackPermissions -ADConnectorAccountName $accountName -ADConnectorAccountDomain $domain -ADobjectDN $ForestDN

Implement Password Writeback

After assigning the permissions in AD, only the feature has to be activated in AADC. The whole process is described in this tutorial from Microsoft — but actually only consists of activating the checkbox.

Overview of the current Tenant and AADC setup and more

Before you move on to the next step, make yourself familiar with the current AADC environment. Which version AADC are you running? Is maybe an update reasonable before the change? (yes — it is!)

And you should also review what you have implemented so far and look at the tools you need, such as the troubleshooting tool.

Also, I highly recommend having a look at the logs to see when something changes or gets out of hand. For monitoring we have the following tools:

All error messages in these tools should be removed or at least known before(!) the migration.

Step 2: Enable PHS

The activation of PHS can and should (!) be done additionally before the change of the authentication. Especially for larger environments this makes a lot of sense — since according to MS documentation “only” ~20,000 password hashes per hour are synchronized.

The whole process is described in this tutorial from Microsoft — but actually only consists of activating the checkbox.

The best way to find out if the hashes have been successfully synchronized is:

  • Check for error messages (see above). If e.g. permissions are still missing this can be found in the event log of the AADC.
  • Use of the troubleshooting tool in AADC

Step 3: Transition to producion

Now that all preparations have been completed, a date for the changeover can be planned. With good planning, the change itself is no longer a major challenge. It is important to know:

  • What is the impact of change?
  • How does the Change work?
  • How do I recognize success?
  • How to make a rollback in an emergency?

What is the impact of change?

Compared to the migration of ADFS, many things remain completely unchanged:

  • Domains in AAD stay managed — no conversion needed
  • Branding and Seamless SSO is already in place
  • Look & Feel for the users
  • Password complexity policy is defined for all synced user in Active Directory
  • All clients that log on directly to Azure AD and have a Primary Refresh Token or log on from the internal LAN and use Seamless Single-Sign On are completely unaffected by the change.

Only authentication processes that are forms-based are affected That means the better your SSO works, the less users will notice even if there are problems. However, there should be no downtime as planned!

How does the Change work?

This is a very simple change in the GUI. If there is a staging server, the change does not need to be made there as well, since AADC makes the change in AAD and each server reads the current configuration there.

How do I recognize success?

How to make a rollback in an emergency?

If unexpected things happen and you decide to roll back, you just have to reset the sign-on method in the wizard. As described above, this is a setting in the AAD that is set by the AADC and a swing to the staging server is pointless.

By changing the authentication method, the PTA Agent on the AADC server was also uninstalled — this will be reinstalled by the rollback.

However, before you initiate a rollback, you should spend some time troubleshooting — preferably first with the tool integrated in AADC described above. Actually, not much can go wrong and it is probably only a small thing.

Step 4: Decommission of the PTA Agents

If everything goes well and you feel safe you can simply uninstall the other (both) PTA agents — after 10 days the objects will be deleted in the AAD as well.


At first glance, the migration seems almost too simple. On closer inspection, however, challenges can arise depending on the size and use of the AD security features. Ideally, this should lead you to rethink your policies and configurations and cut out old habits. Migration is simple, low-risk and worthwhile — so it’s a good idea!