Design Principles

Adherence to Microsoft Specifications and Windows Behavior

While the project aims to align with Microsoft specifications where feasible, our primary guiding principle is adherence to actual Windows behavior. This approach ensures compatibility and interoperability within Microsoft's authentication ecosystem while accommodating any deviations or inaccuracies found in the specifications.

Interaction Diagrams

Since we try to adhere to Windows behavior, it's helpful to review Microsoft design flows which explain those behaviors, such as How it works: Device registration and Primary Refresh Token Issuance. These flows are similar to the behavior of this project, but project specific design flows are provided here for clarity.

Device Enrollment

Device Enrollment

A: Enrollment is first initiated by authenticating to the https://enrollment.manage.microsoft.com resource. This is accomplished using the functions acquire_token_by_username_password_for_device_enrollment(), initiate_device_flow_for_device_enrollment() paired with acquire_token_by_device_flow(), or initiate_acquire_token_by_mfa_flow_for_device_enrollment() paired with acquire_token_by_mfa_flow(). The UserToken from the response is then provided in a call to enroll_device().

B: The enroll_device() function communicates with the TPM and creates 2 RSA keys. One will be used as the transport key, and the other will be used to create a Certificate Signing Request (CSR). The source for this request is found in src/auth.rs within the BrokerClientApplication struct implementation.

C: enroll_device() sends a GET request to https://enterpriseregistration.windows.net requesting a list of available services. This request is defined in [MS-DRS] Section 3.1 and [MS-DVRD] Section 4.3. The source for this request is found in src/discovery.rs.

D: The enroll_device_internal() function processes the public transport key by generating a BCRYPT_RSAKEY_BLOB, which is then encoded in base64 format.

E: The encoded transport key blob is subsequently included in the enrollment request payload, along with the Certificate Signing Request (CSR), which is also base64 encoded. These, included with the enrollment attributes passed to enroll_device(), are sent to the Azure DRS service for enrollment. The DRS service validates the access token received in A, creates a device id, then generates and signs a device certificate as requested. The device certificate is returned to the client.

F: The device certificate is associated with the transport key in the TPM.

MDM enrollment via Intune was implemented in Himmelblau 1.0.

PRT Issuance via Username/Password

PRT Issuance via Username/Password

A: The logon UI passes the UPN and password to acquire_user_prt_by_username_password().

B: build_jwt_by_username_password() gets a nonce from Microsoft Entra ID.

C: build_jwt_by_username_password() constructs the authentication request with the user’s credentials, nonce, and a scope, and signs the request with the Device key. acquire_user_prt_jwt() sends the request to Microsoft Entra ID.

D: Microsoft Entra ID validates the user credentials, the nonce, and device signature, verifies that the device is valid in the tenant and issues the encrypted PRT. Along with the PRT, Microsoft Entra ID also issues a symmetric key, called the Session key encrypted by Microsoft Entra ID using the Transport key. In addition, the Session key is also embedded in the PRT. This Session key acts as the Proof-of-possession (PoP) key for subsequent requests with the PRT. Up to two Kerberos TGTs are embeded in the PRT, labeled tgt_ad and tgt_cloud. The first is an on-prem TGT (if configured), while the second is an Azure cloud TGT.

E: acquire_user_prt_by_username_password() encrypts the PRT using the Transport key and returns the encrypted blob. exchange_prt_for_access_token() can then be called to obtain an access token for the user.