A look at Azure AD Single Sign-On
Microsoft recently released the Azure AD Single Sign On preview feature, which is a way to support Kerberos authentication in to Azure AD. The neat thing about this is that you don’t need ADFS to have an SSO experience if you’ve already got AD infrastructure in place. It works the same way as in-domain authentication, via a Kerberos ticket granting scheme.
This is a somewhat confounding feature for anyone who has experience with Kerberos in Windows because every party needs to be domain-joined for Kerberos to work. This doesn’t seem possible in the cloud considering its a) not your box, and b) it’s over the public internet. Now, you could create one gigantic AD environment in Azure and create a million trusts to each local domain, but that doesn’t scale and managing the security of it would… suck. So how does Azure AD do it?
It’s deceptively simple, actually. Kerberos is a federated authentication protocol. An authority (Active Directory — AD) issues a ticket to a user targeting the service in use which is then handed off to the service by the user. The service validates that the ticket came from a trusted source (the authority — AD) and converts it into a usable identity for the user. The validation is actually pretty simple.
- Both the service and authority know a secret
- The authority encrypts the ticket against the secret
- The service decrypts the ticket using the secret
- The ticket is validated if decryption succeeds
It’s a little more complicated than that, but that’s the gist.
Nothing about this process inherently requires being domain-joined — the only reason (well… not the only reason) you join a machine to a domain is so this secret relationship can be kept in sync.
With this bit of knowledge in hand, it’s not that big a leap to think you can remove some of the infrastructure requirements and have AD issue a ticket to the cloud. In fact, if you’ve had experience with configuring SSO into apps running on non-Windows boxes you know it’s possible because those boxes aren’t domain joined.
So enough background… how does this work?
During installation and configuration:
- A Computer object is created in AD representing Azure AD called AZUREADSSOACC
- Two Service Principal Names (SPNs) are added to the account
- HOST/aadg.windows.net.nsatc.net
- HOST/autologon.microsoftazuread-sso.com
- A password is created for this account (the secret)
- The secret is sent to Azure AD
- Both domains of the SPNs are added as intranet zones to any machine doing SSO
Authentication works as follows:
- When a user hits login.microsoftonline.com and enters their username, an iframe opens up and hits the autologon domain
- The autologon domain returns a 401 with WWW-Authenticate header, which tells the browser it should try and authenticate
- The browser complies since the domain is marked as being in the intranet zone
- The browser requests a Kerberos ticket from AD using the current user’s identity
- AD looks up the requesting autologon domain and finds it’s an SPN for the AZUREADSSOACC computer
- AD creates a ticket for the user and targets it for the AZUREADSSOACC by encrypting it using the account’s secret
- The browser sends the ticket to the autologon domain
- The autologon domain validates the ticket by decrypting it using the secret that was synced
- If the ticket can be decrypted and it meets the usual validation requires (time, replay, realm, etc.) then a session key is pushed up to the parent window
- The parent window observes the session key and auto logs in
The only sort of synchronization that occurs is that initial object creation and secret generation. AD doesn’t actually care that the service isn’t domain joined.
Technically as far a AD knows the service is domain joined by virtue of it having a computer account and secret, but that’s just semantics. AD can’t actually manage the service.
That’s all there is to it.