Hey all!

First of all: Happy New Year and all the best for 2022! May the force be with us…

I’ve been a bit busy by the end of 2021 and took the end of December off to step away from my Mac and servers for a bit. However, with this new year kicking off, it’s time to step up the game again. Hence this first blogpost of 2022!

Today’s topic will be about, what else to kick the year off, Jamf Connect and MS Azure Conditional Access, as I’ve recently been working on some challenge to figure out some behaviour with the password change URL. By diving into the matter, I ended up beyond the initial issue I was troubleshooting: the Azure Change Password URL in the limited browser via the Jamf Connect Menu Bar app, to some impact on Jamf Connect Login.

I’ll split this post in different sections, as I have a feeling it’s gonna be a long one. So if you’re reading this: rule number 1, caffeinate yourself!

Before kicking this off, I want to highlight the difference between ‘Requiring MFA’ and ‘Requiring the device to be compliant’. If you’re only requiring MFA, you may be in a good spot with some success codes added to the JC plists. Requiring ‘device to be compliant’ is however another story, which seems to be complicating things and causing confusion. Hence this blogpost.

Conditional Access blocking access to the password URL

First of all, what are we talking about? Well, nothing more than the change password URL feature you can add to Jamf Connect Menu Bar. In this case for Azure:

Setting this should allow the end user to open a webkit window to login to Azure and change the Azure account password:

Now, that all works fine, just like when you would do it in any browser… as long as you do not have some specific Conditional Access Policies (CAP) enabled in Azure.

If you require MFA for all your Azure resources, that would be fine as the webpage inside this limited browser would still be going through the MFA process.

However, things get a little more complicated if you use other conditions on the CAP, for instance: “Require device to be marked as compliant“. Let’s have a look.

I took my perfectly working Jamf Connect configuration, which was configured against my Azure tenant which had NO MFA and NO Intune/MEM enabled. I didn’t even have a any Intune licenses on it… so I purchased one 🙂 (Yes, I do have access to other Azure Tenants with Intune licenses, but when trying to break things, I prefer to do that on my own test instances… )

Next, I configured the following CAP limiting in to the one and only user with an Intune license:

Important to replicate are the settings for:

  • All Cloud Apps
  • Browsers selected in the Client Apps
  • Require device to be compliant in the grant

Now, those among us paying attention to warnings added by developers may already have noticed the following statement/warning in one of the screenshots above:

Don’t lock yourself out! This policy impacts the Azure portal. Before you continue, ensure that you or someone else will be able to get back into the portal.

Disregard this warning if you are configuring persistent browser session policy that works correctly only if “All cloud apps” are selected.

No, I’m not going to lock myself out, as this policy is only enabled for 1 user… and not my global admin :-). However, there is a big clue here in view of our password change URL: this policy impacts the Azure Portal. More about that later.

With that policy enabled, I tried the password change URL on a Mac which I previously registered to Intune. Just for the record, here is the proof that my test Mac is Compliant, nicely registered to Intune via the Jamf Pro integration:

Before I actually tried to access the change password URL I first checked if I could still authenticate to Jamf Connect to start with…

In the first screenshot I’ve added here above, you can see that I actually had the success code AADSTS50005 added.

<key>SuccessCodes</key>
  <array>
    <string>AADSTS50005</string>
  </array>

This is because without this success code, I ended up with:

This is immediately the first impact of having a CAP set to all cloud apps requiring the device to be compliant. However, adding the success code in the plist allowed Jamf Connect to work fine. This is similar to how we typically work around ‘errors’ for MFA on this ROPG password validation check (other success code needed: AADSTS50076).

However, when I tried the password URL in the limited webkit browser via Jamf Connect, I got stuck at:

Why? Well, if we look at the “More details”, we see that the Azure Portal is complaining about the fact that the Mac is not registered to Azure….

First of all, the fact that this CAP is being evaluated is EXPECTED, because I assigned it to the user I’m logging in with. As per my CAP configuration I showed earlier. However, the fact that the Mac is blocked – reported as unregistered – fuels confusion here.

You may be thinking that the CAP should not even apply here, as we are signing in via Jamf Connect… and if you configured the Jamf Connect app in Azure correctly according to the Jamf documentation, you may remember that you configured it as a “Mobile and Desktop Application” and not as a cloud / web app…

So, the fact that the user account is triggering the CAP is expected, and if I sign in with another user (assigned to the Jamf Connect app) I can log in just fine as the CAP does not trigger (expected). But why does the CAP apply here if we set the CAP to “ALL CLOUD APPS”? Even if you would try to limit the CAP to only selected apps you’ll notice that you can not even select your Jamf Connect app… (because it’s a Mobile/Desktop app!)…

So, why does the CAP apply here? Well, here we go back to the warning I talked about earlier… setting a CAP to “all cloud apps” IMPACTS THE AZURE PORTAL! And, if we look closely to the ‘More info’ section on the password URL error message, we see that it is NOT accessing our Jamf Connect app, but “Microsoft App Access Panel” instead!

This all said, it is totally expected that this CAP is being evaluated…. but… my Mac IS REGISTERED to Azure and IS COMPLIANT ! So why is it being reported as unregistered?

Well, this brings me to the following Microsoft article, or specifically the know behaviour mentioned here: https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-compliant-device#known-behavior

On Windows 7, iOS, Android, macOS, and some third-party web browsers Azure AD identifies the device using a client certificate that is provisioned when the device is registered with Azure AD. When a user first signs in through the browser the user is prompted to select the certificate. The end user must select this certificate before they can continue to use the browser.

Those who have some experience with registering Macs to Azure/ Intune-MEM, may be familiar with the Workplace Join Certificate, which is the certificate that is being installed in the macOS Keychain when registering it to Azure. It is this certificate this known behaviour is talking about, and we can illustrate this by trying to authenticate to Azure in a new browser (or via private/incognito mode). Let’s try to access the change password URL directly from a browser:

As you can see, we initially get the same “error” or message as when we try to access this URL via Jamf Connect, but if we hit continue we get a pop-up prompting us to select our WPJ certificate…. and… after that… all is fine:

If however we try this again in our limited webkit browser… the app seems to continue, but we end up with being instructed to register our device.

If end users then attempt to follow these instructions and register the device again, we end up with a variety of headache inducing issues, duplicate Azure records, breaking compliance, etc…

However, AFAIK, the root cause for this is nothing more than the fact that the limited webkit browser can not display the prompt requesting to select the WPJ certificate, the process continues and end up with Azure (by lack of getting the cert and device details) assessing the device as “not registered”.

That said, I have seen situations where at first glance similar user accounts, on similar devices, within the same scope and settings of the CAPS, do not trigger the prompt to select the cert. Not in the limited webkit browser and not in the full browser, while it does request it when trying the same authentication in a private/incognito browser.

To me this must be related to either SSO or persistent sessions which can be configured in Azure, but as this troubleshooting is already borderline by expertise here, I’d need to explore this thought further. Anyway, from within my realm of expertise, I’m confident to conclude that what I discussed above is expected behaviour for either Jamf Connect, the limited webkit browser and the Azure CAP’s.

Please correct me if I’m wrong.

Now, let’s move to how we can work around this and how to allow end users to access the change password URL via the Jamf Connect Menu Bar app in next section of this blogpost.

Workaround opening a FULL browser via Jamf Connect

Before we work around it from a Jamf Connect Menu Bar point of view, I just want to highlight that you could consider not to scope your CAP to “All Cloud Apps”, or exclude (or not select) the Microsoft Azure Management app…

The Microsoft Azure Management app includes the access to the Azure Portal. But then this leaves us to whether or not you really need or want to limit access to Azure Portal from Compliant devices only or not… which is I guess the reason why you have the CAP to start with.

Same goes for unticking ‘browsers’ in the Client Apps section:

But that even goes further against any reason for why you would want it to be limited to compliant devices only… as no browsers at all would then trigger the CAP.

Leaving this entire discussion for you to discuss internally, let’s have a look at what we can do from a Jamf Connect Menu Bar side to work around this.

If we agree on all the above, concluding it is the limited webkit app breaking the prompt to select the WPJ cert, and considering it works in a full browser… what if we hide the built in ‘change password’ feature for our end users, and create our own via the ‘actions’ feature triggering it to open the URL in a full browser?

Let’s have a look! I’ll try to keep this section short as it is really straight forward.

To start, the documentation: https://docs.jamf.com/jamf-connect/2.7.0/documentation/Custom_Menu_Bar_Action_Items.html?hl=action

As per above, the only things we need to do are:

  • Create an ADDITIONAL plist for the action items, set to the com.jamf.connect.actions domain
  • Configure the custom menu bar items
  • (Optional) hide the built in change password item

A simple example of a plist for the com.jamf.connect.actions would be:


<?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">
    <dict>
                <key>Actions</key>
                <array>
                    <dict>
                        <key>Action</key>
                        <array>
                            <dict>
                                <key>Command</key>
                                <string>url</string>
                                <key>CommandOptions</key>
                             <string>https://account.activedirectory.windowsazure.com/ChangePassword.aspx</string>
                            </dict>
                        </array>
                        <key>Name</key>
                        <string>Click here to change your Azure password</string>
                    </dict>
                </array>
    </dict>
</plist>

Scope that to all your devices using Jamf Connect.

Next, add the following to your existing Jamf Connect Menu Bar plist:

	<key>CustomMenuItems</key>
	<dict>
                <key>actions</key>
                <string>Change Password</string>
	</dict>
        <key>HiddenMenuItems</key>
        <array>
                    <string>changepassword</string>
                    <string>resetpassword</string>
        </array>

As you can see I also added the ‘resetpassword’ field to be hidden as the topic of this blogpost also applies to resetting the password via Azure.

Now, if you push this change to your devices you’ll see that the default change password options are gone and the end user can change the password via our custom action, which will open a FULL browser. Knowing that they will then be able to select the WPJ cert… all will be fine!

Extending the discussion on the issue to Jamf Connect Login

Now, as this all may, imo, explain the behaviour and provide a workaround for Jamf Connect Menu Bar, I realised that scoping a CAP – set to “all cloud apps” and requiring the device to be complaint before it can access the Azure Portal…. actually also breaks Jamf Connect Login:

Attempting to continue here however ends up with a the page not progressing, being stuck… waiting for the cert prompt which can not be displayed (compared to the webkit browser via Jamf Connect Menu Bar where it does continue and ends up with asking to register the Mac).

This here is however creating a chicken or egg situation… especially if you are setting up the Mac for the first time after going through the automated enrolment. Your Azure CAP is blocking the login because it does not consider the Mac to be compliant, but to be able to make it compliant and register it, you need to be able to login… open Self Service… and run the registration policy. And even more, if we look at our Menu Bar discussion above, even making the device compliant does not fix it as the limited webkit browser in Jamf Connect Login would have the same issue.

So this is not good. Hence the Jamf Connect documentation states: https://docs.jamf.com/jamf-connect/2.7.0/documentation/Integrating_with_Microsoft_Azure_AD.html?hl=conditional

If you are using Jamf Connect with Automated Device Enrollment (formerly DEP), remove this application from any conditional access controls. The user will be signing in to the computer before conditional access can be instantiated.

Now, if we go back to the “Setup your device” message and we look at the “more details” section…

… we do see that Jamf Connect is however passing the ID of the JC Azure App… compared to our change password URL which is attempting to access Microsoft App Access Panel (Azure Portal)…. so we can exclude it?

Well… NO because if we set our CAP to “All Cloud Apps” and we try to exclude Jamf Connect….

… we can’t select or find our ‘Jamf Connect’ app…. because… it’s not a cloud / web app…

This actually brings me to a point to conclude: do not set your CAPs to all cloud apps if you are requiring the devices to be compliant. I think limiting it to those cloud apps which really need it can simplify things, but again, I leave that discussion up to you and your Azure/security team.

In next and final section of this blogpost I’ll go through creating a custom app for Jamf Connect Login, which can be excluded from any ‘all cloud app” CAPs and device compliance.

Workaround for Jamf Connect Login: custom cloud app

To do this I based my steps on: https://community.jamf.com/t5/jamf-connect/jamf-connect-and-microsoft-azure-conditional-access/td-p/231944

This article was mainly written in view of the ‘failure’ messages you get in the Azure sign-in logs when doing password validations with ROPG via Jamf Connect, when you have MFA CAPs enabled.

Setting the error code AADSTS50076 as a success code in the JC plist, allows JC to see the error message as a success and consider the password to be valid. However, on Azure side, this may spam the sign-in logs with ‘failures’ stating the users tried to authenticate without MFA.

Anyhow, the success code allows you to make Jamf Connection Menu Bar work without any problems, and like I mentioned earlier, if you only have CAPs which are enforcing MFA, all is good.

In order to work around the impact of CAPs with compliance requirements on Jamf Connect Login, I did however take this workflow as a baseline to fix JCL here.

What I did was basically (if you go to the Github pdf linked in that article):

  • Step One: Create an application registration with a custom API
  • Step Two: Create an application registration using this new API permission
  • Step Three: Create an Azure Conditional Access policy

I didn’t do step 3 as per this blogpost I already had a CAP… which triggered this entire discussion, so what I did here, was to exclude the App I created in step One (so not the native desktop app created in step two):

  • Next, I assigned my endusers (in my case for testing the CAP, the user to which the CAP applies) to the app created in step 2. As this will be the app for which I’ll configure the Jamf Connect plists. No need to assign any users to the app created in step 1.
  • I did not do step 4 (remove all CAPS scoped to ‘all cloud apps’) as doing so would basically make this entire blogpost useless 🙂
  • I also did not do step 5. Instead I just used the same app I created in step 2 for both OIDC and ROPG. When I did however try it, even without removing the API permissions as per (optional) this step, and point ROPG to a different ROPG app in Jamf Connect Login, I ended up with an error ‘no consent’ when validating the password at login. So I kept it at same app for OIDC and ROPG.
  • Finally I configured the Jamf Connect Login and Jamf Connect Menu Bar plists.

Jamf Connect Login plist, with OIDCScopes set to that additional API app we created in step 1. OIDCClientID and OIDCROPGID set to the app we created in step 2 and the custom OIDCProvider and OIDCDiscoveryURL:

<?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">
  <dict>
    <key>AllowNetworkSelection</key>
    <true/>
    <key>OIDCClientID</key>
    <string>97d0a5fb-AAAA-BBBB-CCCC-530ff05e81c2</string>
    <key>OIDCNewPassword</key>
    <false/>
    <key>OIDCProvider</key>
    <string>Custom</string>
    <key>OIDCDiscoveryURL</key>
    <string>https://login.microsoftonline.com/af72a024-AAAA-BBBB-CCCC-fd66bf369fcc/v2.0/.well-known/openid-configuration</string>
    <key>OIDCScopes</key>
    <string>api://9e690060-AAAA-BBBB-CCCC-2e68d657f2ac/jamfconnect</string>
    <key>OIDCROPGID</key>
    <string>97d0a5fb-AAAA-BBBB-CCCC-530ff05e81c2</string>
    <key>OIDCRedirectURI</key>
    <string>https://127.0.0.1/jamfconnect</string>
  </dict>
</plist>

I then also changed my Menu Bar plist to use that same app from step 2:

<?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">
<dict>
	<key>IdPSettings</key>
	<dict>
		<key>Provider</key>
		<string>Azure</string>
		<key>ROPGID</key>
		<string>97d0a5fb-AAAA-BBBB-CCCC-530ff05e81c2</string>
                <key>ChangePasswordURL</key>
                <string>https://account.activedirectory.windowsazure.com/ChangePassword.aspx</string> 
                <key>SuccessCodes</key>
                <array>
                <string>AADSTS50005</string>
                </array>
	</dict>
	<key>Kerberos</key>
	<dict>
		<key>AutoRenewTickets</key>
		<true/>
		<key>Realm</key>
		<string>TRAVELLINGTECHGUY.DEV</string>
	</dict>
	<key>SignIn</key>
	<dict>
		<key>AutoAuthenticate</key>
		<true/>
		<key>RequireSignIn</key>
		<true/>
	</dict>
	<key>CustomMenuItems</key>
	<dict>
                <key>actions</key>
                <string>Change Password</string>
	</dict>
        <key>HiddenMenuItems</key>
        <array>
                <string>changepassword</string>
                <string>resetpassword</string>
        </array>
</dict>
</plist>

This allowed me to log in via Jamf Connect Login, validate the password via ROPG in Login and Menu Bar and use the change password URL via a full browser.

The only thing I do see is that the above workflow, just like when doing MFA for “All Cloud Apps” without deploying the custom setup from the Jamf Nation article, is logging sign-in errors with AADSTS50005 when Jamf Connect Login is validating the password at login via ROPG. However, the login and password validation succeeds, even without adding AADSTS50005 as a success code. I see it first logging a failure against the App we put in the plist (step 2 in my workflow above), followed by a success against the app we created for the custom API. To me this is also expected as the app we actually authenticate to is still the one we can not exclude from the CAP.

Conclusion

I typically come across situations where admins are enforcing MFA for authentications to their iDP. And with MFA, even if a CAP is set to “All Cloud Apps”, we typically do not see much issues.

Jamf Connect Login handles MFA via OIDC (the web app auth) quite well, and for the ROPG password validation, the success code can be added to translate the error message (AADSTS50076) into a validation of the password.

Same goes for Jamf Connect Menu Bar.

However, the usage of the success codes does spam the sign-in logs with ‘failures’ when MFA is triggered by ignored by Jamf Connect and the success code. Hence the reason for this article: https://community.jamf.com/t5/jamf-connect/jamf-connect-and-microsoft-azure-conditional-access/td-p/231944

Now, I do need to give this article/workflow another go in view of purely testing MFA, as for my blog post here I used a CAP requiring the device to be compliant instead of triggering MFA.

One thing I did see however is that if you remove the API permissions as per step 5 in that article the ROPG in Jamf Connect Login hits a ‘no consent’ error when validating the password.

Now, this blog was a totally different setup.

  • By keeping the CAP set to “All Cloud Apps” and requiring the device to be compliant I was able to work around it by adding AADSTS50005 as success code in Menu Bar, and moving the change password URL to a custom action.
  • By doing so, Jamf Connect Menu Bar app works totally fine!
  • However, the fact of keeping the CAP to “All Cloud Apps” spams the logs with AADSTS50005 errors. This regardless of the additional tests with a custom API app (see Jamf Connect Login testing)

  • For Jamf Connect Login, the fact of having an “All Cloud Apps” CAP with “Require device to be compliant” breaks jamf Connect Login. In that case you’ll need to go through a complex setup as per above to be able to exclude the Jamf Connect Login app.
  • Same as with MFA, you will have failures in the sign-in logs

This all leads me to conclude that setting CAPS for MFA or Compliance to “All Cloud Apps” is maybe not the best approach if you are deploying Jamf Connect.

For MFA I would only apply it to a select group of apps, including Microsoft Azure Management (Azure Portal). This should allow you to apply the Jamf Nation article about JC and MFA to avoid the spam of sign-in failures in the logs, and everything, including the default change password feature, will work fine.

For CAPS with “Require the device to be compliant” I’m tempted to say the same. Limit it to those apps for which you really want / need the device to be compliant, and do not select the Microsoft Azure Management or “All Cloud Apps” in the target of the CAP. Your main apps providing access to company data will be protected by the compliance requirement, and for the Azure Portal you can require MFA via a separate CAP for the Microsoft Azure Management app. Doing so there would be no need for any complex setups like this for Jamf Connect Login or Jamf Connect Menu Bar.

Finally, important to mention is also the difference in where you do enforce MFA, as per the Jamf Nation article:

Administrators can enable multi-factor authentication requirements for a user account in two ways:

– Multi-factor Authentication which is reachable via the “All services” list in the Azure portal
– Conditional Access which is reachable via Azure Active Directory under Security

Multi-factor Authentication is a system wide, all login attempts, master switch system for enforcing MFA at authentication. While IP address ranges can be exempted, the rules apply to all authentications.


Conditional Access allows for fine grain details to apply for when MFA is required including exempting MFA for web applications.

Long story short, I’d say: Conditional Access, MFA, Compliance, etc… quite a complex matter, subject to how and where you configure it.

Please, for any Azure Wizards out there, please do not hesitate to add comments, remarks or corrections to anything I’ve been writing here, but as a TLDR I’d like to close this off with: avoid “All Cloud Apps” in your CAPs where possible.

That’s it! As always, if you liked the post, hit the like button, tell your friends about it and leave a comment down below!

Brgds,
TTG