[Last updated 9th November 2022 – note that Microsoft now include this functionality in their own product as written at https://learn.microsoft.com/en-us/azure/active-directory/hybrid/reference-connect-adsyncconfig#set-adsyncexchangehybridpermissions]
[Last updated 11th November 2019 – added support for Exchange Server automapping support, which was announced during Microsoft Ignite 2019 and will be supported in the first half of calendar year 2020. This is supported by adding writeback for msExchDelegateListBL and msExchDelegateListLink attributes. The below Exchange Hybrid writeback script has been updated to support these two attributes.]
[This blog post was last updated 5th October 2017 – added support to Exchange Hybrid for msExchDelegateLinkList attribute which was announced at Microsoft Ignite 2017 for the support of keeping auto-mapping working cross on-premises and the cloud]
[Updated 18th June 2017 in advance of the release of AADConnect version 1.1.553.0. This post contains updates to the below scripts to include the latest attributes synced back to on-premises including publicDelegates, which is used for supporting bi-directional sync for “Send on Behalf” of permissions in Exchange Online/Exchange Server hybrid writeback scenarios]
[Update March 2017 – added another blog post on using the below to fix permission-issue errors on admin and other protected accounts at http://c7solutions.com/2017/03/administrators-aadconnect-and-adminsdholder-issues]
Azure Active Directory has been long the read-only cousin of Active Directory for those Office 365 and Azure users who sync their directory from Active Directory to Azure Active Directory apart from eight attributes for Exchange Server hybrid mode. Not any more. Azure Active Directory writeback is now available. This enables objects to be mastered or changed in Azure Active Directory and written back to on-premises Active Directory.
This writeback includes:
- Devices that can be enrolled with Office 365 MDM or Intune, which will allow login to AD FS controlled resources based on user and the device they are on
- “Modern Groups” in Office 365 can be written back to on-premises Exchange Server 2013 CU8 or later hybrid mode and appear as mail enabled distribution lists on premises. Does not require AAD Premium licences
- Users can change their passwords via the login page or user settings in Office 365 and have that password written back online.
- Exchange Server hybrid writeback is the classic writeback from Azure AD and is the apart from Group Writeback is the only one of these writebacks that does not require Azure AD Premium licences.
User writeback from Azure AD (i.e. users made in Office 365 in the cloud for example) to on-premises Active Directory- Password Hash Sync (this is not really writeback, but its the only permission needed by default for forward sync, so added here)
- Windows 10 devices for “Azure AD Domain Join” functionality
All of these features require AADConnect and not and of the earlier verions. You can add all these writeback functions from the AADConect setup wizard, and if you have used Custom mode, then you will need to implement the following permissions.
In all the below sections you need to grant permission to the connector account. You can find the connector account for your Active Directory forest from the Synchronization Service program > Connectors > double-click your domain > select Connect to Active Directory Forest. The account listed here is the connector account you need to grant permissions to.
SourceAnchor Writeback
For users with (typically) multi-forest deployments or plans or a forest migration, the objectGuid value in Active Directory, which is used as the source for the attribute that keys your on-premises object to your synced cloud object – in AAD sync parlance, this is known as the SourceAnchor. If you set up AADConnect version 1.1.553.0 or later you can opt to change from objectGuid to a new source anchor attribute known as ms-ds-consistencyGuid. To be able to use this new feature you need the ability for AADConnect connector account to be able to read ObjectGUID and then write it back to ms-ds-consistencyGuid. The read permissions are typically available to the connector account without doing anything special, and if AADConnect is installed in Express Mode it will get the write permissions it needs, but as with the rest of this blog, if you are not using Express Mode you need to grant the permissions manually and so write permissions are needed to the ms-ds-consistencyGuid attribute. This can be done with this script.
$accountName = "domain\aad_account" #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is often an account in the form of MSOL_number or AAD_number]. $ForestDN = "DC=contoso,DC=com" $cmd = "dsacls '$ForestDN' /I:S /G '`"$accountName`":WP;ms-ds-consistencyGuid;user'" Invoke-Expression $cmd | Out-Null
$accountName = “domain\aad_account” #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is often an account in the form of MSOL_number or AAD_number]. $ForestDN = “DC=contoso,DC=com” $cmd = “dsacls ‘$ForestDN’ /I:S /G ‘`”$accountName`”:WP;ms-ds-consistencyGuid;user’” Invoke-Expression $cmd | Out-Null [/code]
Note that if you use ms-ds-consistencyGuid then there are changes required on your ADFS deployment as well. The Issuance Transform Rules for the Office 365 Relying Party Trust contains a rule that specifies the ImmutableID (aka AADConnect SourceAnchor) that the user will be identified as for login. By default this is set to ObjectGUID, and if you use AADConnect to set up ADFS for you then the application will update the rule. But if you set up ADFS yourself then you need to update the rule.
Issuance Transform Rules
When Office 365 is configured to federate a domain (use ADFS for authentication of that domain and not Azure AD) then the following are the claims rules that exist out of the box need to be adjusted. This is to support the use of ms-ds-consistencyguid as the immutable ID.
ADFS Management UI > Trust Relationships > Relying Party Trusts
Select Microsoft Office 365 Identity Platform > click Edit Claim Rules
=> issue(store = “Active Directory”, types = (“http://schemas.xmlsoap.org/claims/UPN”, “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID”), query = “samAccountName={0};userPrincipalName,objectGUID;{1}”, param = regexreplace(c.Value, “(?<domain>[^\\]+)\\(?<user>.+)”, “${user}”), param = c.Value);
c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”]
=> issue(store = “Active Directory”, types = (“http://schemas.xmlsoap.org/claims/UPN”, “http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID”), query = “samAccountName={0};userPrincipalName,ms-DS-ConsistencyGUID;{1}”, param = regexreplace(c.Value, “(?<domain>[^\\]+)\\(?<user>.+)”, “${user}”), param = c.Value);
Preparing for Device Writeback
Device Writeback is used where you have an on-premises ADFS server farm and implement Conditional Access on-premises. If you do cloud based authentication, including Pass-Through Auth (PTA) then you have no requirement for Device Writeback.
If you do not have a 2012 R2 or later domain controller then you need to update the schema of your forest. Do this by getting a Windows Server 2012 R2 ISO image and mounting it as a drive. Copy the support/adprep folder from this image or DVD to a 64 bit domain member in the same site as the Schema Master. Then run adprep /forestprep from an admin cmd prompt when logged in as a Schema Admin. The domain member needs to be a 64 bit domain joined machine for adprep.exe to run.
Wait for the schema changes to replicate around the network.
Import the cmdlets needed to configure your Active Directory for writeback by running Import-Module ‘C:\Program Files\Microsoft Azure Active Directory Connect\AdPrep\AdSyncPrep.psm1’ from an administrative PowerShell session. You need Azure AD Global Admin and Enterprise Admin permissions for Azure and local AD forest respectively. The cmdlets for this are obtained by running the Azure AD Connect tool.
$accountName = "domain\aad_account" #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is often an account in the form of MSOL_number or AAD_number]. Initialize-ADSyncDeviceWriteBack -AdConnectorAccount $accountName -DomainName contoso.com #[domain where devices will be created].
In the domain partition you should now see an OU called RegisteredDevices. The AADSync account now has permissions to write objects to this container.
In Azure AD Connect, if you get the error “This feature is disabled because there is no eligible forest with appropriate permissions for device writeback” then you need to complete the steps in this section and click Previous in the AADConnect wizard to go back to the “Connect your directories” page and then you can click Next to return to the “Optional features” page. This time the Device Writeback option will not be greyed out.
Device Writeback needs a 2012 R2 or later AD FS server and WAP to make use of the device info in the Active Directory (for example, conditional access to resources based on the user and the device they are using). Once Device Writeback is prepared for with these cmdlets and the AADConnect Synchronization Options page is enabled for Device Writeback then the following will appear in Active Directory:
Not shown in the above, but adding the Display Name column in Active Directory Users and Computers tells you the device name. The registered owner and registered users of the device are available to view, but as they are SID values, they are not really readable.
Preparing for Group Writeback
Writing Office 365 “Modern Groups” back to Active Directory on-premises requires Exchange Server 2013 CU8 or later schema updates and servers installed. To create the OU and permissions required for Group Writeback you need to do the following.
Import the cmdlets needed to configure your Active Directory for writeback by running Import-Module ‘C:\Program Files\Microsoft Azure Active Directory Connect\AdPrep\AdSyncPrep.psm1’ from an administrative PowerShell session. You need Domain Admin permissions for the domain in the local AD forest that you will write back groups to. The cmdlets for this are obtained by running the Azure AD Connect tool.
$accountName = "domain\aad_account" #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is often an account in the form of MSOL_number or AAD_number]. $cloudGroupOU = "OU=CloudGroups,DC=contoso,DC=com" Initialize-ADSyncGroupWriteBack -AdConnectorAccount $accountName -GroupWriteBackContainerDN $cloudGroupOU
Once these cmdlets are run the AADSync account will have permissions to write objects to this OU. You can view the permissions in Active Directory Users and Computers for this OU if you enable Advanced mode in that program. There should be a permission entry for this account that is not inherited from the parent OU’s.
At the time of writing, the distribution list that is created on writeback from Azure AD will not appear in the Global Address List in Outlook etc. or allow on-premises mailboxes to send to these internal only cloud based groups. To add it to the address book you need to create a new subdomain, update public DNS and add send connectors to hybrid Exchange Server. This is all outlined in https://technet.microsoft.com/en-us/library/mt668829(v=exchg.150).aspx. This ensure’s that on-premises mailboxes can deliver to groups as internal senders and not require external senders enabled on the group. To add the group to the Global Address List you need to run Update-AddressList in Exchange Server. Once group writeback is prepared for using these cmdlets here and AADConnect has had it enabled during the Synchronization Options page, you should see the groups appearing in the selected OU as shown:
And you should find that on-premises users can send email to these groups as well.
Preparing for Password Writeback
The option for users to change their passwords in the cloud and have then written back to on-premises (with multifactor authentication and proof of right to change the password) is also available in Office 365 / Azure AD with the Premium Azure Active Directory or Enterprise Mobility Pack licence.
To enable password writeback for AADConnect you need to enable the Password Writeback option in AADConnect synchronization settings and then run the following three PowerShell cmdlets on the AADSync server:
Get-ADSyncConnector | fl name,AADPasswordResetConfiguration Get-ADSyncAADPasswordResetConfiguration -Connector "contoso.onmicrosoft.com - AAD" Set-ADSyncAADPasswordResetConfiguration -Connector "contoso.onmicrosoft.com - AAD" -Enable $true
The first of these cmdlets lists the ADSync connectors and the name and password reset state of the connector. You need the name of the AAD connector. The middle cmdlet tells you the state of password writeback on that connector and the last cmdlet enables it if needed. The name of the connector is required in these last two cmdlets.
To set the permissions on-premises for the passwords to be written back the following script is needed:
$passwordOU = "DC=contoso,DC=com" #[you can scope this down to a specific OU] $accountName = "domain\aad_account" #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is often an account in the form of MSOL_number or AAD_number]. $cmd = "dsacls.exe '$passwordOU' /I:S /G '`"$accountName`":CA;`"Reset Password`";user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls.exe '$passwordOU' /I:S /G '`"$accountName`":CA;`"Change Password`";user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls.exe '$passwordOU' /I:S /G '`"$accountName`":WP;lockoutTime;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls.exe '$passwordOU' /I:S /G '`"$accountName`":WP;pwdLastSet;user'" Invoke-Expression $cmd | Out-Null
Finally you need to run the above once per domain.
Preparing for Exchange Server Hybrid Writeback
Hybrid mode in Exchange Server requires the writing back on eight attributes from Azure AD to Active Directory. The list of attributes written back is found here. The following script will set these permissions for you in the OU you select (or as shown at the root of the domain). The DirSync tool used to do all this permissioning for you, but the AADSync tool does not. Therefore scripts such as this are required. This script sets lots of permissions on these eight attributes, but for clarify on running the script the output of the script is sent to Null. Remove the “| Out-Null” from the script to see the changes as they occur (the script also takes a lot longer to run).
$accountName = "domain\aad_account" #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is often an account in the form of MSOL_number or AAD_number]. $HybridOU = "DC=contoso,DC=com" #Object type: user $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;proxyAddresses;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchUCVoiceMailSettings;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchUserHoldPolicies;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchArchiveStatus;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchSafeSendersHash;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchBlockedSendersHash;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchSafeRecipientsHash;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msDS-ExternalDirectoryObjectID;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;publicDelegates;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchDelegateLinkList;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchDelegateListBL;user'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchDelegateListLink ;user'" Invoke-Expression $cmd | Out-Null #Object type: iNetOrgPerson $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;proxyAddresses;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchUCVoiceMailSettings;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchUserHoldPolicies;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchArchiveStatus;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchSafeSendersHash;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchBlockedSendersHash;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchSafeRecipientsHash;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msDS-ExternalDirectoryObjectID;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;publicDelegates;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchDelegateLinkList;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchDelegateListBL;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;msExchDelegateListLink;iNetOrgPerson'" Invoke-Expression $cmd | Out-Null #Object type: group $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;proxyAddresses;group'" Invoke-Expression $cmd | Out-Null #Object type: contact $cmd = "dsacls '$HybridOU' /I:S /G '`"$accountName`":WP;proxyAddresses;contact'" Invoke-Expression $cmd | Out-Null
Finally you need to run the above once per domain.
Preparing for User Writeback
[This functionality is not in the current builds of AADConnect]
Currently in preview at the time of writing, you are able to make users in Azure Active Directory (cloud users as Office 365 would call them) and write them back to on-premises Active Directory. The users password is not written back and so needs changing before the user can login on-premises.
To prepare the on-premises Active Directory to writeback user objects you need to run this script. This is contained in AdSyncPrep.psm1 and that is installed as part of Azure AD Connect. Azure AD Connect will install Azure AD Sync, which is needed to do the writeback. To load the AdSyncPrep.psm1 module into PowerShell run Import-Module ‘C:\Program Files\Microsoft Azure Active Directory Connect\AdPrep\AdSyncPrep.psm1’ from an administrative PowerShell session.
$accountName = "domain\aad_account" #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is an account usually in the form of AAD_number]. $cloudUserOU = "OU=CloudUsers,DC=contoso,DC=com" Initialize-ADSyncUserWriteBack -AdConnectorAccount $accountName -UserWriteBackContainerDN $cloudUserOU
Once the next AADSync occurs you should see users in the OU used above that match the cloud users in Office 365 as shown:
Prepare for Password Hash Sync
This set of PowerShell ensures that the AADConnect account has the correct permissions to read password hashes from the Active Directory when they are changed, so that the service can sync them to the cloud. You need this permission whenever you enable Password Hash Sync (which could be in conjunction with another authentication method as well)
$DomainDN = "DC=contoso,DC=com" $accountName = "domain\aad_account" #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is often an account in the form of MSOL_number or AAD_number]. $cmd = "dsacls.exe '$DomainDN' /G '`"$accountName`":CA;`"Replicating Directory Changes`";'" Invoke-Expression $cmd | Out-Null $cmd = "dsacls.exe '$DomainDN' /G '`"$accountName`":CA;`"Replicating Directory Changes All`";'" Invoke-Expression $cmd | Out-Null
Prepare for Windows 10 Registered Device Writeback Sync
Windows 10 devices that are joined to your domain can be written to Azure Active Directory as a registered device, and so conditional access rules on device ownership can be enforced. To do this you need to import the AdSyncPrep.psm1 module. This module supports the following two additional cmdlets to prepare your Active Directory for Windows 10 device sync:
CD "C:\Program Files\Microsoft Azure Active Directory Connect\AdPrep" Import-Module .\AdSyncPrep.psm1 Initialize-ADSyncDomainJoinedComputerSync Initialize-ADSyncNGCKeysWriteBack
These cmdlets are run as follows:
$accountName = "domain\aad_account" #[this is the account that will be used by Azure AD Connect Sync to manage objects in the directory, this is often an account in the form of MSOL_number or AAD_number]. $azureAdCreds = Get-Credential #[Azure Active Directory administrator account] CD "C:\Program Files\Microsoft Azure Active Directory Connect\AdPrep" Import-Module .\AdSyncPrep.psm1 Initialize-ADSyncDomainJoinedComputerSync -AdConnectorAccount $accountName -AzureADCredentials $azureAdCreds Initialize-ADSyncNGCKeysWriteBack -AdConnectorAccount $accountName
To successfully run these cmdlets you need to have the latest version of the Microsoft Online PowerShell modules installed (the V1.1 versions, not the V2.0 preview). You can get these from https://www.powershellgallery.com/packages/MSOnline (which in turn needs MSOL Signin Assistant from https://www.microsoft.com/en-us/download/details.aspx?id=41950 and the Windows Management Framework v5 from https://www.microsoft.com/en-us/download/details.aspx?id=50395). If you get errors in the above, make sure you have the correct version, download from above and try the scripts again.
Once complete, open Active Directory Sites and Services and from the View menu Show Services Node. Then you should see the GUID of your domain under the Device Registration Configuration container.
Leave a Reply