Azure AD Join Single Sign-on: follow the key

Posted by

You already authenticated to an Azure AD identity on an Azure AD joined Windows 10 device after signing in with Windows Hello for Business. This Azure AD identity is synchronized from an on-premises Active Directory domain and your Windows 10 device happens to be connected to the corporate network with line of sight to domain controllers. What you don’t want is to get user name and password prompts for access to on-premises printers, file shares and other resources with Kerberos or NTLM authentication. How can this Windows session avoid prompts for on-premises Active Directory authentication if it does not have the password of the user (because of the Windows Hello for Business sign-in)?

Microsoft calls this “Azure AD Join Single Sign-on” as described in this article: https://docs.microsoft.com/en-us/windows/security/identity-protection/hello-for-business/hello-hybrid-aadj-sso-base. This article mentions the term “Key trust model”, so let’s follow the key to see how the Azure AD joined Windows 10 device gets a Kerberos TGT from a domain controller for the logged on user. The Azure AD joined Windows 10 device accomplishes this even though it does not have an on-premises Active Directory computer object and it does not have a secure channel to any domain controller.

When a user on an Azure AD joined Windows 10 device sets up Windows Hello, a public / private key pair is generated. The private key goes into the TPM chip on the device. The public key, however, goes on a nice little journey. First of all, it can be found in a self-signed certificate in the user certificate store on the device.

We will use the 10 bytes D70BDEE9F322E931CCE0 to keep track of the key in this example.

Windows 10 then writes this key into the Azure AD object of the user. The user’s Azure AD object thus accumulates all keys from all devices where that user set up Windows Hello for Business. These Windows Hello for Business keys go into the attribute “searchableDeviceKey”, from where they can be accessed using Azure AD Graph API: https://graph.windows.net/<TenantId>/users/<UserUPN>?api-version=1.6-internal&$select=searchableDeviceKey

The following simple PowerShell script can be used to extract the Windows Hello for Business keys from a given Azure AD user. You need to modify the script with your Tenant ID and your Azure AD user’s UPN at the beginning; the script uses the Powershell Client ID and requires you to enter the user’s or some administrator’s credentials. Note that you must have the Azure AD Powershell module or the Azure AD Preview Powershell module installed.

Get-WHfBDeviceKeys-from-AzureAD

If, as in this example, the user has set up Windows Hello for Business on 5 devices, then 5 keys are returned.

The base64 encoded key material from the first key is

After base64 decoding we get

Now, Azure AD Connect takes over and synchronizes the key from searchableDeviceKey to the user’s on-premises AD object into the attribute msDS-KeyCredentialLink. Note that msDS-KeyCredentialLink is introduced with the Windows Server 2016 AD schema and only Windows Server 2016 domain controllers can make use of it. You can see the value of msDS-KeyCredentialLink with ldp.exe:

The number of entries should match the number from the PowerShell output, 5 in this case. One of the keys is the one we are following.

Whenever the user signs in to the Azure AD joined Windows 10 device, Azure AD sends the name of the on-premises domain the user is a member of back to the device. With this knowledge, the device tries to find domain controllers for this domain using DNS and Netbios broadcasts; the device succeeds if it is on the corporate network. Next, the device contacts each domain controller one by one until it finds a domain controller that is on Windows Server 2016 or newer. It does so by connection-less LDAP requests over UDP (CLDAP), exactly in the same way that the command nltest /dsgetdc:<domain>.com /DS_10 does it. Thanks to André Mieth for pointing this out.

Once a Windows Server 2016 (or newer) domain controller is found, the Azure AD joined Windows 10 device starts talking Kerberos to get a TGT. Upon first try, the domain controller tells the device that Kerberos pre-authentication is required.

The client obeys and sends the self-signed certificate for pre-authentication in the next Kerberos AS-REQ.

Obviously, the self-signed certificate contains the key we are following. The domain controller checks if the key is present in the user’s msDS-KeyCredentialLink attribute, note that only Windows Server 2016 (or newer) domain controllers can do that. If the domain controller finds the key, it notes the pre-authentication method in the event log and issues a TGT.


On the side: for a successful Kerberos protocol exchange, the domain controller also needs to provide something to prove that it is valid. It does so by sending a certificate to the Windows 10 device. This certificate needs to contain the KDC Authentication enhanced key usage; and the Windows 10 device must be able to reach a CRL distribution point via HTTP. For a detailed explanation see the already mentioned article https://docs.microsoft.com/en-us/windows/security/identity-protection/hello-for-business/hello-hybrid-aadj-sso-base.

2 comments

    1. Public facing is not necessary. An internal CRL distribution point sill suffice. This is because we are talking about a scenario where a line of sight to domain controllers is required anyway; and line of sight to domain controllers implies that an internal CRL distribution point should be reachable.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s