UPDATE 06/11/19

Following a change in Azure, there is a small change in how to assign specific users to the Jamf Connect app. As mentioned below, we need to configure the app as 'Default Client Type = Public'. However when doing so, Azure will hide the 'User and Groups' option in the Enterprise Application.

As mentioned/updated in the Jamf Connect Admin Guide you need to temporarily toggle this switch to 'No' in case you want to assign specific users to the Jamf Connect app. Once you have assigned (or changed) your Jamf Connect users, switch it back to 'Yes'.
UPDATE 16/07/19

In order to get the Admin role working and make some user (who have the admin role assigned according to the manifest, see below), an additional key is now needed in Jamf Connect Login: OIDCAdminAttribute.


Starting in Jamf Connect Login 1.2.1, Login will look at the "groups" attribute in the ID token to determine administrative roles, rather than the "roles" attribute as in earlier versions of Jamf Connect Login. It seems that this change was implemented for OneLogin, but it affects Azure as well. Not sure if this will stay like this.

To clarify, the CreateAdminUser key only creates the user as Admin upon initial creation:

The OIDCAAdmin and Attribute keys forces the account to follow the role you assigned to the user in Azure at each login:

If you only have the CreaetAdminUser key set, the user will be demote to standard at the next login.

There we go! Jamf launched Jamf Connect Login and Jamf Connect Verify with Azure integration: Jamf Connect Azure

Also, Nomad Pro has been rebranded to Jamf Connect Sync (Okta only).

My goal is to do a couple of blog post on the above products, but combining them in one big post would make this post a bit too long. Hence, let’s start with Jamf Connect Login and Azure integration. And this will already be one of those longer posts… ☕️☕️☕️

In one of my previous post I discussed Nomad Login+ Okta. This is now part of Jamf Connect, as depending the configuration the tool can be used for both Okta as Azure. I do have Jamf Connect Login with Okta on my ‘blog to-do list’ in order to go through the changes and discuss how to deploy it.

I’ll also leave Jamf Connect Verify for another time as it requires an additional installation (not included in the Jamf Connect installer).

Jamf Connect Notify (previously DEPNotify) is however part of Jamf Connect, so let’s do that today as well.

So the goal for today’s post:

  • Deploy Jamf Connect
  • Integrate it with Azure
  • Launch Notify during the Jamf Connect Login process.

Cool, lets take it out for a spin! Just be aware, while the product is awesome (really I love it!), the configuration does require some precision work!

To reduce my typing, I’ll refer to Jamf Connect Login as ‘JCL’ and Jamf Connect Notify as ‘JCN’ as from now.


  • JCL Trial (download it herewhen purchasing JCL you will need to deploy a license file as well).
  • Microsoft Azure account with Azure Active Directory
  • Native ‘Jamf Connect Login’ app in Azure (to be created)
  • Some coffee, Red Bull or any other preferred caffeinated substance

Deploy Jamf Connect Login with Azure Integration: Admin Guide

"Jamf Connect Login provides support for Microsoft Azure AD (Active Directory) and can be used to replace the standard macOS loginwindow with Azure Loginwindow. With Azure Loginwindow, you can do the following:

Authenticate via a native app in Azure 
Use multi-factor authentication (MFA) and support conditional access 
Enable Azure AD and Azure DFS (Directory Federation Services) 
Create a local account on a macOS computer"

Lets first start with the Azure side of the deployment. Before we can deploy JCL to our Macs, we need to configure some stuff in Azure. First, you’ll need to create a “native” app:

Go to Azure Active Directory -> App Registrations and create a new app.

Give it a name (Jamf Connect Login), set the Application type to ‘native and add the following redirect URL:

UPDATE 13/08/19: New settings for Azure:

Set default client type to ‘Public YES’ to allow ROPG/ROPC:

By default, all users in the Azure Directory can authenticate to the app, but if you want to limit access you can specifically assign users to it.:

Go to Azure Active Directory – Enterprise Applications – Jamf Connect Login and click on the number under ‘Total Users”. Next you can assign users to the app to restrict usage. However, see below, you might want to define some user roles first.
Note: You can also hide the Jamf Connect Login app from the users portal. As the purpose of this native app is authentication on the macOS LoginWindow, there is no need for the users to see it in their Azure user portal:
Go the properties of the app and set ‘Visible to users” to ‘No’

Now, one of the best features in JCL is the possibility to create local Standard versus Admin account on the Mac, based on the role you assign them in the Azure app. I don’t know what you think, but I love this feature! To do this, we need to create some roles in the Azure app manifest.

So let’s go back to Azure Active Directory – App registrations – Manifest. You need to add some code to the manifest to define the app roles.

I only created two: Standard and Admin. Just copy-paste the code below and change the “id”. The “id” is just a random UUID which you can easily create in macOS terminal by running:

uuidgen | tr "[:upper:]" "[:lower:]"


  "appRoles": [
      "allowedMemberTypes": [
      "displayName": "Standard",
      "id": "211b8058-b630-401c-b79f-334a7777f15a",
      "isEnabled": true,
      "description": "Members of the Standard group.",
      "value": "Standard"
      "allowedMemberTypes": [
      "displayName": "Admin",
      "id": "44bf4a1e-b28e-47e1-aa8d-2d5d2063f7bf",
      "isEnabled": true,
      "description": "Members of the Admin group.",
      "value": "Admin"

Next, go back to Azure Active Directory -> Enterprise applications -> Jamf Connect Login. Now you can assign users and define if JCL will create a Standard or Admin user on the Mac for them:

I created a user called ‘Standard’ which I assigned the Standard role, and TTG the Admin role.
Note: We'll see below how to tell JCL which role is considered to be Admins, but another way to create admin accounts through JCL is by setting the 'CreateAdmin' key in the preferences. This will however create Admin accounts for ALL users.
Note: If you are using Jamf Connect Login with automated MDM enrollment (formerly DEP), remove this application from any conditional access controls. The user will be signing into the system before conditional access can be instantiated.

So, that’s all for the Azure configuration. Lets now have a look at how to deploy JCL and configure the settings. First we need to create a configuration profile. You could also configure it via a script and the ‘defaults write’ command, but then this script needs to be deployed as part of the install package (see below). Deploying it via a Jamf Pro @Enrolment policy will not work as we need to be sure that this script runs before the user hits the LoginWindow… (and we have no control over that).

I’ll go with a config profile here. If you look at the Admin Guide, you will see that you need to create the profile and sign it before you upload it to Jamf Pro. Pretty sure that this is the best practice, but whether I’m lazy or just stubborn, I’ll leave that to you. I’m just going with a normal PLIST with basic settings and upload it as a custom preference. Hence I don’t have to sign it. It works, but nevertheless, I would advice to follow the official workflow and make a signed profile.

First of all here is my basic PLIST. For now I’m just adding the 4 mandatory keys, defining the Admin user role and specifying the path to my Notify (JCN) script. More about that below.

4 mandatory keys:

  • OIDCClientID (Azure App ID)
  • OIDCProvider (Set it to Azure – can be set to Okta as well)
  • OIDCROPGID (Azure App ID)
  • OIDCRedirectURI

Admin user role:

  • OIDCAdmin (Set it to the Admin role you created in the Azure Manifest)
  • OIDCAdminAttribute (Set it to ‘roles’ according to the update mentioned above)

Notify ScriptPath:

  • ScriptPath
*** UPDATED 16th of July 2019***

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

You will need your Azure Enterprise App ID:

Upload it to Jamf Pro as a Custom Setting in a configuration profile:

Again, a signed profile following the instructions of the admin guide is preferred, also due to the location where these setting will be written in the Library. But yet again, stubborn as I am, this works well for testing.

At this point, you could just upload the official JCL installer to your Cloud distribution point and deploy it via a prestage enrollment package. For prestage enrollments packages to work, it needs to be a signed package and deployed via a Cloud Distribution point. The official Jamf JCL installer is correctly signed of course.

However, as you have seen, I added a key to configure Notify (JCN) to the JCL PLIST as well. So I need to deploy the script, images and other items which I’m using in the Notify process as well. Hence we need to repackage the JCL installer, and add what we need for or Notify process to work.

As I did not want to touch the official installer I created my own package as follows. First Jamf Composer:

As you can see above, I’m deploying the official JCL installer (renamed) to the /tmp folder, and my Notify script (see below) and images to /usr/local/bin and /usr/local/images. In my demo, I’m quickly deploying Chrome and Firefox and throwing some dummy status bars in JCN. Hence the additional images/icons.

Note: Make sure the permissions of all your folders, and especially your Notify script are set correctly: root/wheel 755.

Next, I’m adding a post install script to run the official installer from the /tmp folder and enable JCN:

Don’t forget to add /usr/local/bin to the authchanger command… I did not think of that and waisted time troubleshooting miles away from the issue… ‘why is Notify not launching’ 🙂
Note: The Notify mechanism is not included in the loginwindow application by default. You can use the authchanger to enable both the Notify mechanism and RunScript mechanisms. The admin guide mentions the command to enable JCN ('authchanger -reset -OIDC -preAuth JamfConnectLogin:RunScript,privileged JamfConnectLogin:Notify'), but don't forget to specify the path:
#Enable Notify
/usr/local/bin/authchanger -reset -OIDC -preAuth JamfConnectLogin:RunScript,privileged JamfConnectLogin:Notify

I build this as a pkg but before signing it with my Developer Certificate, I’m passing this pkg through Munkipkg. Just to make sure everything is repackaged as it should be, as you might run against some issues when trying to sign the package or when deploying it through a prestage.

You could off course package everything manually in Munkipkg, but I like the drag and drop of Composer.

In Munkipkg I import my Composer pkg, and repackage it again. Just define the path to your pkg and give the project a name (ttgJC). Munkipkg will unpack your pkg and write all files in a folder (named to the project name) in the working directory:

$ munkipkg --import /path-to-pkg/ttgJC.pkg ttgJC

Next I repackaged it again with Munkipkg. Just run Munkipkg with the project name:

$ munkipkg ttgJC
Munkipkg will build the package again in the ‘build’ folder of the project.

The final step is signing the package, as otherwise our custom package will not run during the prestage process. For instance with a Developer Certificate:

$ productsign --sign 'Developer ID Installer: Travelling Tech Guy (3********S)' '/path-to-your-munkiproject/build/ttgJC.pkg' '/destination-path-signed-pkg/ttgJCSigned.pkg'

Done! Upload this signed package to your Cloud Distribution Point, add it to a prestage, skip account creation and there we go! Jamf Connect Login with account creation based on Azure and Notify deploying anything you want before the end user even reaches the Desktop! MAGIC!

Just for the record, here is my sample Notify script. Apart from deploying Chrome and Firefox, I also added a safety net to make sure the Jamf Binary is installed before it calls custom triggers from Jamf Pro. When testing in VM’s it happens that the installation of the Jamf Binary via MDM has some delay, but it might be a good safety net for real deployments as well.


### Do it!

echo "STARTING RUN" >> /tmp/output.txt

# Set a main image
# Image can be up to 660x105 it will scale up or down proportionally to fit

echo "Command: Image: /usr/local/images/TTG.png" >> /var/tmp/depnotify.log

# Set the Main Title at the top of the window

echo "Command: MainTitle: Welcome to your new Mac!" >> /var/tmp/depnotify.log

# Set the Body Text

echo "Command: MainText: We are setting up a few things for you automatically.\\nJust grab a coffee! It won't take long!." >> /var/tmp/depnotify.log

echo "Status: Preparing new machine" >> /var/tmp/depnotify.log 

echo "Command: Determinate: 5" >> /var/tmp/depnotify.log
sleep 3
echo "Status: Checking some Magic for you..." >> /var/tmp/depnotify.log 

#adding a safety net here to make sure the Jamf Binary is present. Just in case there is some delay on the installation via MDM

while [ ! -f /usr/local/bin/jamf ]
  sleep 2

### Jamf Triggers

sleep 3
echo "Command: Image: /usr/local/images/Chrome.png" >> /var/tmp/depnotify.log
echo "Status: Installing Google Chrome" >> /var/tmp/depnotify.log 

/usr/local/bin/jamf policy -event installChrome

sleep 3
echo "Command: Image: /usr/local/images/Firefox.png" >> /var/tmp/depnotify.log
echo "Status: Installing Firefox" >> /var/tmp/depnotify.log 

/usr/local/bin/jamf policy -event installFirefox

sleep 3
echo "Command: Image: /usr/local/images/Pirate.png" >> /var/tmp/depnotify.log
echo "Status: Doing more fancy stuff... you don't want to know..." >> /var/tmp/depnotify.log

### AD Bind? Nah, who needs an AD bind nowadays... we'll just skip that.

sleep 5
echo "Command: Image: /usr/local/images/TTG.png" >> /var/tmp/depnotify.log
echo "Status: Almost done!" >> /var/tmp/depnotify.log 

### Clean Up

sleep 3
echo "Command: Quit" >> /var/tmp/depnotify.log

sleep 1
rm -rf /var/tmp/depnotify.log

That’s it! I hope this covers all you need to do a basic deployment of Jamf Connect Login with Azure and Notify enabled.

I might do another more advanced tutorial later, but have a look at the additional keys you can set in the configuration profile here.

Also coming up next, Jamf Connect Verify, Jamf Connect Sync, ….

Let me know if you have any comments, remarks or questions!