In 2017 Microsoft has made some major improvements to their Managed authentication model to make it a viable competitor to the cumbersome Federated model. As a refresher, Federated identity requires Microsoft ADFS infrastructure deployed (along with ADConnect for AD Sync), and to make it highly available entails multiple servers deployed in multiple datacenters/Azure, global load balancing of the internet-facing URL with Azure Traffic Manager – dependencies on your private cloud to authenticate to the public cloud. Managed identity still uses ADConnect for AD Sync but the biggest drawback is that you didn’t get the “seamless” single signon (SSO) experience that ADFS provides, only “same sign on” (SSO) and needing to reenter your credentials.
Microsoft has recently added Seamless Single Signon and Pass-Thru Authentication (as an alternative to password-hash synchronization in high security environments, but out of scope for this article) to ADConnect, in efforts to further eliminate the ADFS dependencies previously mentioned, and with this I’ve been working a large number of projects in planning / executing a move away from ADFS.
What I’ve found is that it’s always been a grey area on how long this process takes, given most of the documentation calls for using the Convert-MSOLDomainToStandard cmdlet and dealing with the password conversion process. If you follow these steps there’s an easier way to do it.
Contents
Step 1 – Check Local Active Directory
The first step is ensuring that you have local AD setup and able to support Password Sync. One of the Microsoft Premier Field Engineers (PFE) wrote a great blog on this in 2016:
https://blogs.technet.microsoft.com/askpfeplat/2016/12/19/convert-a-federated-domain-in-azure-ad-to-managed-and-use-password-sync-step-by-step/
“First, ensure your Azure AD Connect Sync ID has “Replicate Directory Changes” and “Replicate Directory Changes All” permissions in AD (For Password Sync to function properly). If you did not set this up initially, you will have to do this prior to configuring”
This can be done thru Active Directory Users & Computers
(If you don’t know what the account name is, open the Azure AD Connect wizard and View current Configuration
You can also check via Powershell using a handy script created by Bugra Postaci, entering in the account used by ADConnect for synchronization. Save this in Notepad as checkperms.ps1 then run from Powershell using the command .\checkrep.ps1 “<account>”, where <account> is the account seen in the Azure AD Connect wizard under View Current Configuration
param( [string] $userName=””)
function Check-ADUserPermission(
[System.DirectoryServices.DirectoryEntry]$entry,
[string]$user,
[string]$permission)
{
$dse = [ADSI]”LDAP://Rootdse”
$ext = [ADSI](“LDAP://CN=Extended-Rights,” + $dse.ConfigurationNamingContext)$right = $ext.psbase.Children |
? { $_.DisplayName -eq $permission }if($right -ne $null)
{
$perms = $entry.psbase.ObjectSecurity.Access |
? { $_.IdentityReference -eq $user } |
? { $_.ObjectType -eq [GUID]$right.RightsGuid.Value }return ($perms -ne $null)
}
else
{
Write-Warning “Permission ‘$permission’ not found.”
return $false
}
}# Globals
$replicationPermissionName = “Replicating Directory Changes”
# Main()
$dse = [ADSI]”LDAP://Rootdse”
$entries = @(
[ADSI](“LDAP://” + $dse.defaultNamingContext),
[ADSI](“LDAP://” + $dse.configurationNamingContext));Write-Host “User ‘$userName’: ”
foreach($entry in $entries)
{
$result = Check-ADUserPermission $entry $userName $replicationPermissionNameif($result)
{
Write-Host “`thas a ‘$replicationPermissionName’ permission on ‘$($entry.distinguishedName)'” `
-ForegroundColor Green
}
else
{
Write-Host “`thas no a ‘$replicationPermissionName’ permission on ‘$($entry.distinguishedName)'” `
-ForegroundColor Red
}
}
If this happens to fail on either one, save this in Notepad as fixperms.ps1 then run from Powershell using the command .\fixperms.ps1 “<account>”, where <account> is the account seen in the Azure AD Connect wizard under View Current Configuration.
param( [string] $Identity=””)
$RootDSE = [ADSI]”LDAP://RootDSE”
$DefaultNamingContext = $RootDse.defaultNamingContext
$ConfigurationNamingContext = $RootDse.configurationNamingContext
$UserPrincipal = New-Object Security.Principal.NTAccount(“$Identity”)DSACLS “$DefaultNamingContext” /G “$($UserPrincipal):CA;Replicating Directory Changes”
DSACLS “$ConfigurationNamingContext” /G “$($UserPrincipal):CA;Replicating Directory Changes”
Step 2 – Check Password Sync Health
Once access to AD and password hashes are verified, now we want to ensure password sync to Azure AD is healthy.From the Technet Blog: “On the Azure AD Connect server, run CheckPWSync.ps1 to see if Password Sync is enabled”.
Save this in Notepad as CheckPWSync.ps1 then run from Powershell using the command ./CheckPWSync.ps1
Import-Module ADSync
$connectors = Get-ADSyncConnector
$aadConnectors = $connectors | Where-Object {$_.SubType -eq “Windows Azure Active Directory (Microsoft)”}
$adConnectors = $connectors | Where-Object {$_.ConnectorTypeName -eq “AD”}
if ($aadConnectors -ne $null -and $adConnectors -ne $null)
{
if ($aadConnectors.Count -eq 1)
{
$features = Get-ADSyncAADCompanyFeature -ConnectorName $aadConnectors[0].Name
Write-Host
Write-Host “Password sync feature enabled in your Azure AD directory: ” $features.PasswordHashSync
foreach ($adConnector in $adConnectors)
{
Write-Host
Write-Host “Password sync channel status BEGIN ——————————————————- ”
Write-Host
Get-ADSyncAADPasswordSyncConfiguration -SourceConnector $adConnector.Name
Write-Host
$pingEvents =
Get-EventLog -LogName “Application” -Source “Directory Synchronization” -InstanceId 654 -After (Get-Date).AddHours(-3) |
Where-Object { $_.Message.ToUpperInvariant().Contains($adConnector.Identifier.ToString(“D”).ToUpperInvariant()) } |
Sort-Object { $_.Time } -Descending
if ($pingEvents -ne $null)
{
Write-Host “Latest heart beat event (within last 3 hours). Time ” $pingEvents[0].TimeWritten
}
else
{
Write-Warning “No ping event found within last 3 hours.”
}
Write-Host
Write-Host “Password sync channel status END ——————————————————- ”
Write-Host
}
}
else
{
Write-Warning “More than one Azure AD Connectors found. Please update the script to use the appropriate Connector.”
}
}
Write-Host
if ($aadConnectors -eq $null)
{
Write-Warning “No Azure AD Connector was found.”
}
if ($adConnectors -eq $null)
{
Write-Warning “No AD DS Connector was found.”
}
Write-Host
If it comes back showing where Enabled is False:
Enable Password hash synchronization in ADConnect
Then restart the service & force a full Sync
Restart-Service ADSync
Import-module ADSync
Start-ADSyncSyncCycle -PolicyType Initial
Once you’ve enabled Password sync, force a full password sync using the TriggerFullPWSync.ps1 script below (I’ve modified it to automatically detect the connectors).
Save this in Notepad as TriggerFullPWSync.ps1 then run from Powershell using the command ./TriggerFullPWSync.ps1
# Run script on AD Connect Server to force a full synchronization of your on prem users password with Azure AD
# Change domain.com to your on prem domain name to match your connector name in AD Connect
# Change aadtenant to your AAD tenant to match your connector name in AD Connect
Import-Module adsync
$connectors = Get-ADSyncConnector
$aadConnector = $connectors | Where-Object {$_.SubType -eq “Windows Azure Active Directory (Microsoft)”}
$adConnectors= $connectors | Where-Object {$_.ConnectorTypeName -eq “AD”}
$c = Get-ADSyncConnector -Name $adConnector.Name
$p = New-Object Microsoft.IdentityManagement.PowerShell.ObjectModel.ConfigurationParameter “Microsoft.Synchronize.ForceFullPasswordSync”, String, ConnectorGlobal, $null, $null, $null
$p.Value = 1
$c.GlobalParameters.Remove($p.Name)
$c.GlobalParameters.Add($p)
$c = Add-ADSyncConnector -Connector $c
Set-ADSyncAADPasswordSyncConfiguration -SourceConnector $adConnector -TargetConnector $aadConnector -Enable $false
Set-ADSyncAADPasswordSyncConfiguration -SourceConnector $adConnector -TargetConnector $aadConnector -Enable $true
You’ll also know that Password Sync is working because the Application Log on your ADConnect server should provide 4 event log Entries to that effect
Step 3 – Making the Switch
If you’ve made it to step 3 and everything else is working OK – rest assured that you’ve already made it thru the hardest parts and are ready to make the switch.
First, create / verify an “In Cloud” account that is a global administrator exists to perform the steps. Using a Federated account is not a recommended in case something goes wrong!
NOTE: This account doesn’t need any licenses.
Login into your ADConnect server
Open Powershell (Run as Administrator)
NOTE: You’ll need the Windows Azure Active Directory Powershell module installed.
You can download the final v1 build 9031 here:
https://social.technet.microsoft.com/wiki/contents/articles/28552.microsoft-azure-active-directory-powershell-module-version-release-history.aspx#Preview_Versions_of_MSOL_PowerShell
Import-Module MSOnline
Connect-MSOLService
As a final preflight check, perform a Get-MSOLDomain for your list of domains
Before the change we are redirected to ADFS:
Now we run the Powershell command
Set-MsolDomainAuthentication –DomainName <domain> –Authentication Managed
Within seconds we’re ready to login, and now have home realm discovery day at Office 365
We can run Get-MSOLDomain and verify that <domain> has been changed to Managed
There is no need to convert any accounts – since they exist as synchronized identities with a password hash stored. All users are ready to go!
If something goes wrong and you decide that you want to go back to your Federated identity model, just log into your Primary ADFS server and run the following commands:
Import-Module MSOnline
Connect-MSOLService
Import-Module ADFS
Convert-MsolDomainToFederated -DomainName <domain>
Once you’ve finished, you’ll be directed to your ADFS login page to authentication.
Hi Chris,
Don’t you also need to clean your ADFS environment by also running the Convert-MSOLDomainToStandard command? Otherwise your users are still flagged as Federated users.
Thanks,
Current Microsoft guidance on the switch:
https://docs.microsoft.com/en-us/azure/active-directory/hybrid/plan-migrate-adfs-pass-through-authentication
With AD Connect 1.1.819 and later, it more closer matches this process, woohoo!
Thanks! A life saver, it helped me during my conversion. I had to wait 40 min after Set-MsolDomainAuthentication, before it worked again.
It’s so much easier to do in ADConnect now after version 1.1.819!
On line 9 of the password health check script, it fails stating that the Connectorname parameter doesn’t exist.
Changed the line to the below and it works successfully;
$features = Get-ADSyncAADCompanyFeature
Thanks for that feedback!