ADFS Authentication flow with Multiple Forests

So recently I had the time and motivation to try to understand exactly how authentication works in a multi-forest ADFS environment. In my case I was preparing to visit a customer that would need this kind of setup and wanted to brush up.

I couldn’t find any decent information on the web so thought I would share my findings here.

2 forests, forest A (IMTest) has ADFS and AAD Sync deployed and has a transitive forest trust with forest B (TestDomain)


I wanted to know when a user from TestDomain authenticates, does ADFS authenticate directly with a TestDomain DC by way of a Kerberos referral or does it go via a IMTest DC which authenticates the remote forest user on it’s behalf? Don’t forget ADFS is installed into the IMTest forest.

As a result of this then, does ADFS need any connectivity to the TestDomain DC’s?

I asked this question on a few forums and MS kindly came back and told me that all auth traffic would flow via the IMTest DC and no networking would be required between ADFS and TestDomain. However they didn’t really back it up and I wanted to be sure so I built a lab and set about testing.

I found that as soon as I blocked traffic between ADFS and the TestDomain DC my authentication for the TestDomain user broke throwing a random ADFS error. I checked the firewall logs and sure enough found some Kerberos and LDAP packets being dropped.


So i installed WireShark onto the ADFS Farm server and the results were quite educational.


So WireShark can be a little hard to interpret so lets talk through the highlighted sections.

  1. The ADFS server ( send an AS-REQ to the IMTest DC( This is the Kerberos process of requesting a TGT (Token granting ticket) from the AS (Authentication Server)
  2. AS on the IMTest DC responds with KDC_ERR_WRONG_REALM. This is because the UPN suffix of the user does not belong to the IMTest forest but is associated with the TestDomain Forest trust. If we take a closer look at the contents of this packet we can see that the reply contains the new KDC to contact in the CRealm fieldCapture4
  3. So a new AS-REQ is sent but this time to the TestDomain DC (
  4. The TestDomain AS responds with ERR_PREAUTH_REQUIRED. This is expected behaviour as the client requested a ticket but did not include the pre-authentication data with it. Windows uses this technique to determine the supported encryption types.
  5. This is followed by another AS-REQ but this time containing the required authentication contained within the padata header of the packet.
  6. The TestDomain DC responds with AS-REP. This contains the TGT needed to continue and request service tickets. Here it is..Capture5
  7. So lets continue with the next Kerberos step of contacting the TGS (Ticket Granting Server) to ask for a service ticket. This is shown below in the TGS-REQ to the TestDomain DC but note the highlighted sname (Service name we are requesting access to) shows KRBTGT IMTEST.K1TECHNOLOGY.CO.UK. This is the TGT service in IMTest.Capture6
  8. The TestDomain DC responds with a TGS-REP which contains the service ticket.
  9. Next ADFS takes the service ticket and presents it to the IMTest DC but this time we are referencing SKFed…. This is ADFS.Capture7
  10. Voila Authentication is completed! Well, the user has been authenticated at least. The process is actually then repeated by ADFS to grant the user access to the ADFS service account principal. This is required in order to be able to do an LDAP bind and retrieve the account attributes it needs to evaluate the claim and build the ADFS token. Clearly there is another part where ADFS issues the client a token to take to Office 365 but that is well covered elsewhere on the web.

So what did I learn?

  • ADFS needs TCP/88 (Kerberos) and TCP/389 (LDAP) connectivity to every forest you plan to use it with.
  • Make sure your UPN suffixes are registered correctly in your forest trusts else the first Realm referral won’t work.
  • Finally it’s also important that ADFS is able to resolve each of these domains.

I hope this helps, it’s taken me almost a day of investigation to bottom this out but now I properly understand the authentication flow.

Thanks to Joji over at Technet Blogs for this post that helped me understand what I was looking at.