Azure AD Join process has a lot of process behind the scene and admin or user (based on permissions) can join devices to Azure AD in several ways

  • Through out-of-box experience (OOBE)
  • Through settings after configuring the device with local account

In both cases, the process of join device is the same

  • Join device to Azure AD
  • User authenticates via MFA
  • Accepts terms from Intune MDM
  • Windows 10 device register to Azure AD
  • Windows 10 device enrolls into MDM and policy
  • User login into Windows 10 device
  • Windows 10 device receive device configuration and device compliance
Let’s dig into the details of what happens at each phase:

Join device to Azure AD

When a user turns a device for the first time the user will see the OOBE. Once the user has gone through the initial pages like choosing language/region, accepting legal terms and connecting to the WiFi, the user sees the experience that allows the user to configure the device with a particular account.

The first detail to know is that this experience is web driven and runs under a particular “temporal” user that is created just before the experience shows. This differs from Windows 7 or Windows 8.1 where all pages are local and run as SYSTEM up to the point of user login.

Image result for windows 10 oobe azure ad

The Web pages are rendered in a special host called the Cloud eXperience Host (CXH) which has access to particular WinRT APIs needed for setting up the device.

Once the CXH is launched it navigates to a web app that will orchestrate the setup process. If the device runs Windows Professional the user will see a page presenting the option to configure the device as work-owned (using a work account) or personal (using a Microsoft account).

If the device runs Windows Enterprise or Windows Home this page won’t show but instead will default to work-owned or personal respectively.

Once the user has chosen to configure the device as work-owned, the user will have the option to join the device to Azure AD or to create a local account.

The current experience shows the option to join the device to a domain however this option will guide the user to setup a local account for the user to run Domain Join via Settings afterward.

If the user runs Azure AD Join from Settings the user will see the experience described from this point on.

Once, choosing Azure AD Join the CXH will navigate to the Azure AD Join web app that is hosted in the following location:

This web app is mainly “client” code in the form of HTML and JavaScript that calls particular WinRT APIs in the system via the CXH.

User authenticates via MFA (as need)

Next, the web app will reach out to Azure AD to discover auth end-points by retrieving the OpenID configuration:


Configuration is retrieved by obtaining the following JSON document:

{ “authorization_endpoint”:””, “token_endpoint”:””, “token_endpoint_auth_methods_supported”:[“client_secret_post”,”private_key_jwt”], “jwks_uri”:””, “response_modes_supported”:[“query”,”fragment”,”form_post”], “subject_types_supported”:[“pairwise”], “id_token_signing_alg_values_supported”:[“RS256”], “http_logout_supported”:true, “response_types_supported”:[“code”,”id_token”,”code id_token”,”token id_token”,”token”], “scopes_supported”:[“openid”], “issuer”:”{tenantid}/”, “claims_supported”:[“sub”,”iss”,”aud”,”exp”,”iat”,”auth_time”,”acr”,”amr”,”nonce”,”email”,”given_name”,”family_name”,”nickname”], “microsoft_multi_refresh_token”:true, “check_session_iframe”:””, “end_session_endpoint”:””, “userinfo_endpoint”:”” }

The web app will build a sign-in request using the discovered authorization endpoint to obtain a token to Azure DRS:

GET ?client_id=01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9 &msafed=0 &nonce=5724294428562708 &prompt=login & &response_type=id_token &scope=openid+sid &uxoptin=true &windows_api_version=2.0


  • The value of the parameter client_id corresponds to the one of Azure DRS. This is interesting because the redirect URI is not the Azure DRS end-point but the Azure AD Join web app.
  • The token requested is an ID token. This is because the Azure AD Join web app needs to get claims from the token that need to pass to APIs for discovery, registration and MDM enrollment.
  • There is a parameter particular to Windows to specify the API version. The value of 2.0 allows obtaining MDM related URLs as claims in the ID token.

The user will see the sign-in page where to enter credentials and once the user types the username the page will discover the corresponding realm information.

This will determine whether the user needs to be redirected to a different STS (Secure Token Service) like an AD FS on-premises. This is done by retrieving realm information about the user’s domain name:

GET ? &api-version=2.1

The following is an example of a JSON object for the realm information for a federated tenant:

{ “IsDomainVerified”:0, “NameSpaceType”:”Federated”, “federation_protocol”:”WSTrust”, “Login”:””, “AuthURL”:””, “DomainName”:””, “FederationBrandName”:”EliShlomo” }

For managed tenants only, an authentication buffer is created locally and temporary cached for automatic sign-in of the user to Windows at the end of OOBE (this doesn’t happen if run from Settings which will require a sign-out and a manual sign-in by the user).

Federated tenant users will need to authenticate to the Windows logon UI after OOBE has completed.

Credentials are posted to Azure AD for authentication to the login end-point along with a few parameters indicating that this is a CXH driven authentication. This is useful to tweak some behaviors on the service side: ?cxhflow=MOSET &cxhver=1.0 &cxhplatform=Desktop

Note that it indicates where the join is run from, the version of the host and the platform. After authentication succeeds, an ID token is generated and posted back to the Azure AD Join web app.

The following is an example of the contents of the token:

{ upn : “” instance : “NA” amr : [“pwd”,”mfa”] tid : “df5be8b1-f322-456c-acff-b13066d72402” sid : “S-1-12-1-1875800440-1278975369-1393086615-305892544” nbf : 1453828246 ver : “1.0” mdm_enrollment_url : “” family_name : “Cadena” sub : “4ySzMn-D18vwlmB4lWNipSg7Y5-qDVg9g41XVyoRvF4” user_setting_sync_url : “Discovery:” onprem_sid : “S-1-5-21-1515794938-1370939529-2107639213-1112” oid : “6fce7178-9d89-4c3b-97d0-0853c08c3b12” exp : 1453832146 given_name : “eshlomo” iat : 1453828246 iss : “” aud : “dd762716-544d-4aeb-a526-687b73838a22” name : “Eli Shlomo” unique_name : “” tenant_display_name : “Microsoft” primary_sid : “S-1-5-21-1515794938-1370939529-2107639213-1112” }

Please note that this information is cached locally in the device and is accessible after device registration completes through the following APIs in dsreg.dll:

DsrGetJoinInfo or DsrGetJoinInfoEx

The following claims in particular contain URLs which are used later on to complete configuration of the device.


Accepts terms from Intune MDM

Next step is for the user to accept the terms from the Intune MDM. If there is a corresponding URL configured in Azure AD for the MDM app for this user, the ID token will contain a claim mdm_tou_url.

If present the web app will navigate to the URL and the user will be presented with the terms of acceptance, then accept the page posts back an acceptance buffer that the web app will use later when calling the MDM enrollment API.

Windows 10 device register to Azure AD

Based on javaScript the web app calls a WinRT worker API that in turn calls APIs for discovery of the registration service, device registration and MDM enrollment:


This API first calls a discovery API to obtain information about the registration service. This API is an internal Win32 API implemented in dsreg.dll which retrieves the discovery data document from:

This document contains information about Azure DRS registration and authentication end-points including the federation STS end-point (if configuration is federated), the Azure DRS URI, the end-point for Microsoft Passport provisioning, etc. One example of this document is shown below:

These URLs/URIs are added to the cache data accessible by the DsrGetJoinInfoEx API after device registration completes.

With the discovery data and the ID token obtained during authentication the worker API then calls another API to perform device registration. This is another internal Win32 API in dsreg.dll which does the following:

  • Generates a key pair for the device certificate.
  • Generates a certificate signing request (CSR) using the key pair above
  • Generates a second key pair that will be used to bind SSO tokens physically to the device when authenticating to Azure AD later on. This key is typically called the storage transport key (Kstk) and is derived from the SRK (Storage Root Key) of the device TPM.
  • Sends a device registration request to Azure DRS passing along the ID token, the generated CSR and the public portion of the storage/transport key along with its attestation data.

Once the request comes to Azure DRS, the service will validate the token, will create a corresponding device object in Azure AD and will generate and send back a certificate to the device.

The API in turn will install the certificate into the LocalMachine\MY store.

Using Windows PowerShell you can check the certificate checking for the CN=MS-Organization-Access particular issuer:

PS C:\> dir Cert:\LocalMachine\My\ | where { $_.Issuer -match “CN=MS-Organization-Access” } | fl Subject : CN=fbfcc7db-3b31-4818-aaf0-15aeb Issuer : DC=net + DC=windows + CN=MS-Organization-Access + OU=82dbaca4-3e81-46ca-9c73-0950c1eaca97 Thumbprint : A948413B32FA0A6435275693D4136BE10DFB4E97 FriendlyName : NotBefore : 1/30/2017 11:22:29 AM NotAfter : 1/27/2022 12:17:39 AM Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid…}


  • DeviceId is a GUID generated by Azure DRS. Note that this is the same value in the Subject field of the certificate.
  • AlternativeSecurityIds contains the certificate thumbprint with a specific scheme format. This is how Azure AD will find the device object when the device presents the certificate upon authentication.
  • The storage transport key is stored in the device object in an attribute non-visible through Graph API.

Windows 10 device enrolls into MDM and policy

If registration successful the worker API calls the MDM enrollment API passing along the following:

  • An access token to the MDM enrollment service (MDM application in Azure AD).
  • The acceptance of terms blob obtained from the corresponding MDM page (if present).
To obtain the MDM access token it first obtains an auth code by authenticating to the MDM enrollment service application silently relying on SSO cookies obtained previously during authentication to Azure DRS:

GET ?client_id=29d9ed98-a469-4536-ade2-f981bc1d605e &msafed=0 &nonce=7912667160858957 & &response_type=code &resource=


  • Client ID corresponds to the one of the MDM app in Azure AD.
  • The response type requested is a code.
  • The resource is the value for the mdm_enrollment_url claim in the ID token.

The worker API will then use the code to obtain an access token for enrollment to happen. It does so by posting the code to the token end-point:


grant_type=authorization_code &code=AAABAAAAiL9Kn2Z27UubvWFPbm0gLViFwdiaP_FoKfldoPoZ6-o_aBfB1H8nQJgkWzbD1W1J8F3hCrO7aTO69QAib-PfvEFZTC3BwK53vNfuZ576-HunV5qGup1Pbf5N8p3Dv-HcZ tMIUpgvmqwTCJ1mS4e4M-0cPaCejrV4imOrVOocm92F9TS5ME-d44PQ2aQVXqLSKfGsvUEnbnzN1InYTmkk_sHaxZOiAYPofFR4AeuM5EmaNCK3e5lQVqHaBIXmGJnRRpKxOqQAAPxXtPrh 5089NjNhEOgdkywyqCOSmV7FEejcSycZmpPHuvzxuUq85V_g0XS2a0y6OSgoh8lqSIBVXerds7etsC6USg4HMnCKxmZHrhxTjAp0citwUoGV3Ch6uOOgVpOKt7D4AZIfTYVEhz9p-7371EG ZaIkC6jKdfg3SwxJj4gfC_WfeJc6NGCJE2iWcIQpFmywHEBAnNrQv_2ZmyTq3TEnycijLpK8IUU5ZwtqAqAFoi7qRKb0R6GlRSnqCS9WKQaRbGkzF17IENorhD01MYwWCOrtcMW4oKfy7Qw Ehn5oPEIoaoQzLsbwjL5Wor90sbmltHCXN5KECSkMnMaa5Yz0YPsdh4ULaOZDwXrJrJxau4_DCxHss_0ENu2mjfH3tumTjG-s3A-qoHiUHjxUXbls_BdQ0X8SVLjECz1mLVsOe_rNc_bsUl PTdAzLSyQkeRTWFYb19X3CwPCAA &client_id=29d9ed98-a469-4536-ade2-f981bc1d605e & &resource=

The worker API will get back a bearer token with an access token, an ID token and a refresh token. It extracts the access token and passes it to the MDM API.

MDM enrollment occurs and sign-in policy is obtained as part of the payload coming from enrollment.

User login into Windows 10 device

Once MDM enrollment completes it is time for the user to sign in. The user is automatically signed in if the tenant is managed.

This is accomplished by taking the authentication buffer obtained during authentication to Azure DRS and passing it to the LSA to the Cloud Authentication Provider which in turn authenticates both the user and the device with Azure AD.

For more information about how this works in detail look for a future post on SSO in Windows 10 devices.

Note that for a future update of Windows we have plans to extend the user’s automatic sign-in behavior to federated tenants as well.

Windows 10 device receive configuration and compliance

If the device is InstantGo capable, device disk encryption is enabled and the key is sent to Azure AD to be registered in the corresponding device object.

For example by the BitLocker Drive Encryption Service (BDESVC) which uses the following end-point discoverable through the DsrGetJoinInfoEx API to write the key in Azure AD:


The way the service authenticates the device to the end-point is by relying on the SSO capabilities of Windows 10. For more information about this please look for a future post about SSO in Windows 10 devices.

Windows 10 device settings are applied

Once authenticated settings are retrieved and applied to the local device. It will rely on information returned by DsrGetJoinInfo to reach out to the service (i.e. user_setting_sync_url claim of ID token initially obtained, accessible through the DsrGetJoinInfo API).


The Azure AD Join process is prety simple but behind the ,scene there’s a lot of actions and information, from the first step of join device until enroll to Intune MDM.