Let’s Get Conditional - Jamf and Company Portal.app Registration Deconstructed (Part 1 - Client Side)

This is the second of a multi-part series about the macOS Intune and Azure AD integration for inventory data and Conditional Access with Jamf Pro.

The topic of this post is explaining the macOS device registration process (client side) of the integration performed by an end user to start the inventory data sync and place the key on the device for Conditional Access.

TL;DR: The macOS device runs a Jamf Pro policy that calls Company Portal.app with the -r (registration only flag) that places the WPJ key and then jamfAAD reads that and the created device AAD ID and posts with that ID to Azure along with Jamf Pro data.

This video shows the registration process taken by an end user and the on screen prompts as well as the WPJ key in the login.keychain.

Under the hood of the Registration Policy and its order of operations…

In this example we will see the following on screen and in the logs.

They play out in this order:

  1. Device Launches Self Service.app

  2. Executes policy that calls Company Portal.app with the registration flag

  3. User signs into Company Portal.app with Azure AD credentials and Company Portal.app places the WPJ key in the users login.keychain; it also makes an AAD shell record of the given macOS device for later use by Jamf Pro (will be covered in upcoming server side blog post)

  4. User closes Company Portal.app, and jamfAAD does a sign-in via the Jamf Native macOS Connector, and asks to read the users login.keychain to read the WPJ key

  5. The data jamfAAD gathers is sent back to Jamf Pro


Open the Self Service.app to launch the registration policy.

Open the Self Service.app to launch the registration policy.

Trigger the registration policy.

Trigger the registration policy.

When the registration policy is trigged via the Self Service.app a binary called jamfAAD is used. jamfAAD is going to then call Company Portal.app using the specially built -r flag.

Found in /var/log/jamf.log:

Sun Apr 26 22:06:14 test-mbp jamf[1480]: Executing Policy Register With AAD

In Unified macOS System Logging:

default 2020-04-26 22:06:15.055131 -0500 JamfAAD Launching Company Portal

The end user would then be presented with the Company Portal.app.

The end user would then be presented with the Company Portal.app.

The end user would then be presented with the Company Portal.app sign-in page with the application in the registration mode.

The end user would then be presented with the Company Portal.app sign-in page with the application in the registration mode.

After the user completes the sign-in Company Portal.app will then perform the Workplace Join.

After the user completes the sign-in Company Portal.app will then perform the Workplace Join.

After the user completes the sign-in Company Portal.app will then perform the Workplace Join.

After the user completes the sign-in Company Portal.app will then perform the Workplace Join.

With the Workplace Join complete Company Portal.app will exit and inform jamfAAD of it’s completion and pass an exit code.

With the Workplace Join complete Company Portal.app will exit and inform jamfAAD of it’s completion and pass an exit code.

WPJ key created by Company Portal.app in the login.keychain.

WPJ key created by Company Portal.app in the login.keychain.

From Company Portal.log:

2020-04-27 03:07:10.363 VERB com.microsoft.ssp.telemetry TID=10318 AriaTelemetryService.swift: 283 (sendEvent(featureArea:type:eventTitle:duration:result:target:location:resultData:error:context:workflowData:clientRequestId:shouldSanitizeStrings:)) Sending event using aria: OutgoingServiceRequest : { clientRequestId = "REDACTED"; context = "TenantID:REDACTED"; durationMs = 304; eventTitle = "Auth_FetchSvcToken"; featureArea = Login; result = Succeeded; target = AADWPJToken; }

2020-04-27 03:07:12.149 VERB com.microsoft.ssp.telemetry TID=10971 AriaTelemetryService.swift: 283 (sendEvent(featureArea:type:eventTitle:duration:result:target:location:resultData:error:context:workflowData:clientRequestId:shouldSanitizeStrings:)) Sending event using aria: OutgoingServiceRequest : { clientRequestId = "REDACTED"; context = partnerFlow; durationMs = 2091; eventTitle = "WPJ_DeviceRegistration"; featureArea = WPJ; result = Succeeded; target = "TokenFetchDuration: 305.7299852371216"; }

2020-04-27 03:07:12.156 VERB com.microsoft.ssp.telemetry TID=10971 AriaTelemetryService.swift: 283 (sendEvent(featureArea:type:eventTitle:duration:result:target:location:resultData:error:context:workflowData:clientRequestId:shouldSanitizeStrings:)) Sending event using aria: InAppProcess : { context = partnerFlow; durationMs = 2375; eventTitle = CompleteWPJOperation; featureArea = WPJ; result = Succeeded; }

2020-04-27 03:07:19.995 INFO com.microsoft.ssp.workplaceJoinSdk TID=9811 WorkplaceJoinManager.swift: 845 (workplaceClient(_:logMessage:)) INFO: [2020-04-27 03:07:19 +0000]getRegistrationInformation: Retrieved certificate thumbprint 2020-04-27 03:07:19.996 INFO com.microsoft.ssp.workplaceJoin TID=9811 WorkplaceJoinManager.swift: 54 (cachedWorkPlaceJoinState) Cached workplace join state set to: Optional(__C.WorkPlaceJoinState(rawValue: 2)))

2020-04-27 03:07:19.996 VERB com.microsoft.ssp.telemetry TID=9811 AriaTelemetryService.swift: 283 (sendEvent(featureArea:type:eventTitle:duration:result:target:location:resultData:error:context:workflowData:clientRequestId:shouldSanitizeStrings:)) Sending event using aria: InAppProcess : { context = partnerFlow; eventTitle = CompanyPortalExited; featureArea = General; result = Succeeded; resultData = 0; }

After the Workplace Join completes Company Portal.app will call back to jamfAAD with an exit code. jamfAAD will then run and gather the info of the WPJ key info, UPN, and AAD ID created for the new device record on AAD by Company Portal.app and submit that information to Jamf Pro.

Possible Comapny Portal.app exit codes:

  • success = 0
  • defaultError = 1
  • userAbandoned = 64
  • registrationError = 65
  • registrationDeviceCapError = 66
  • registrationKeychainError = 67
  • authenticationError = 68
  • networkError = 69
  • commandLineError = 70

In Unified macOS System Logging:

default 2020-04-26 22:07:22.174916 -0500 JamfAAD Collecting Azure Active Directory ID default 2020-04-26 22:07:22.241349 -0500 JamfAAD TID = 11075 ADAL 2.7.12 Mac 10.15.4 [2020-04-27 03:07:22 - UUID-HERE] No cached preferred_network for authority default 2020-04-26 22:07:22.381583 -0500 JamfAAD Task <UUID-HERE>.<1> received response, status 200 content K default 2020-04-26 22:08:09.647316 -0500 JamfAAD 0x600000ba4000 commited /Users/intune2/Library/Keychains/login.keychain-db.sb-XX to /Users/bob.lutz/Library/Keychains/login.keychain-db

jamfAAD will perform a sign-in to the Microsoft AAD endpoint

jamfAAD will perform a sign-in to the Microsoft AAD endpoint

jamfAAD will then ask for access to the login.keychain to read the WPJ key and AAD info. We will want to ensure the end user clicks Always Allow so that jamfAAD can use this info later for daily check-ins as well.

jamfAAD will then ask for access to the login.keychain to read the WPJ key and AAD info. We will want to ensure the end user clicks Always Allow so that jamfAAD can use this info later for daily check-ins as well.

After the end user allows jamfAAD to access the login.keychain the data is then sent to Jamf Pro

jamfAAD in Unified macOS System Logging:

default 2020-04-26 22:08:09.659507 -0500 JamfAAD AAD ID acquired for macOS user account bob.lutz

info 2020-04-26 23:07:12.496853 -0500 JamfAAD Requesting Azure tenant info from jamf daemon

info 2020-04-26 23:07:12.498259 -0500 JamfAAD creating client

info 2020-04-26 23:07:12.500330 -0500 JamfAAD connecting client

Previous
Previous

Let’s Get Conditional - Jamf and Company Portal.app Registration Deconstructed (Part 2 - Server Side)

Next
Next

Let’s Get Conditional - Enterprise Applications Explained