Jamf Blog
How to . . .
December 28, 2021 by Sean Rabbitt

How-to: Azure Conditional Access and Jamf Connect

Finding "failed" login attempts in Azure sign-in logs? Learn:

  • How the ROPG workflow and Jamf Connect communicate
  • How to make an app registration in Microsoft Azure Active Directory that allows for Conditional Access policies
  • How to make Conditional Access policies NOT apply to the ROPG workflow

Problem

Administrators may observe failed login attempts in the log for the enterprise application created in Microsoft Azure Active Directory when using Jamf Connect and a Conditional Access policy that requires Multi-Factor Authentication (MFA) for the target of "All cloud apps." While this is expected behavior of the Resource Owner Password Grant (ROPG) workflow, it may trigger a user appearing in the Risky Sign-Ins in Azure Active Directory security reports.

What is happening

The target of "All cloud apps" applies policies far beyond the logins to specific cloud services and applies policies to non-interactive workflows like those with ROPG. Specifically, the "All cloud apps" appears to apply to any application requesting a login with the scope of any of the following:

openid profile email

The Open ID Connect 2.0 specification uses these default scopes to obtain an access or identity token for a client application. Consequently, in its default configuration, Jamf Connect login uses the openid profile email scope, and the only way to apply a CA policy in this default behavior is to apply the policy to "All cloud apps" with NO exceptions applied or the CA policy will break.

Administrators have multiple options for enforcing MFA on the Jamf Connect login screen:

  • Simplest, but most impact on user logins:
    Set hard requirements for MFA via the older method of Azure Multi-Factor Authentication which applies an MFA requirement to ALL logins to ANY service for a specific user. Ignore failed logins in the sign-in logs for ROPG checks of the password. (Additional information on how to determine if a failed login is due to Jamf Connect menu bar agent doing an ROPG request is below.)
  • Simple, but may affect other services:
    Create a Conditional Access policy applied to "All cloud apps" requiring multi-factor authentication for login. Do NOT use an exception to the policy as that appears to break the functionality of the CA rule as of testing done 10DEC2021. Ignore failed logins in the sign-in logs for ROPG checks of the password.
  • Complex, but exacting:
    Follow the instructions in the Jamf Nation post "Creating a custom scope for Jamf Connect in Azure for Conditional Access policies" to create a custom scope for Jamf Connect applications (you’ll need to sign into Jamf Nation or create an account to access it). Verify that no policies are created that apply to "All cloud apps" so as to not affect the ROPG workflow. CA policy will be applied as expected to the Jamf Connect login application and ROPG check will appear as a successful login in sign-in logs.

Azure Multi-factor Authentication vs. Conditional Access

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 when MFA is required, including exempting MFA for web applications.

Resource Owner Password Grant workflow

Jamf Connect uses an ROPG workflow to synchronize the user's password in the identity provider with the password on the user's client machine. The user name and the password are sent to the identity provider in a "non-interactive" login to receive a response. This means that the user is not prompted for any sort of user name or password when logging in; Jamf Connect is using the information securely stored in the user’s keychain for this event.

For Azure, the responses are one of the following:

Success, no MFA requirements: An access, refresh, and ID token encoded in HS256

Success, MFA required through a policy: An error response like:

 AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access [application UUID]
  • Failure, bad password or user name: An error response like:
 AADSTS50126: Error validating credentials due to invalid username or password.

As long as the user password is correct, the ROPG flow has succeeded - the password has been validated to be correct. Whereas Jamf Connect has no need for the access, refresh, and ID token to keep the local password in sync with the identity provider, an appropriate error response is interpreted as a successful password check.

Reference: https://docs.jamf.com/jamf-connect/administrator-guide/Authentication_Protocols.html

Diagnosing MFA vs. failed password in Azure logs

Navigate to Azure Active Directory → Enterprise Applications and select the name of your Jamf Connect application in Azure. Navigate to Activity → Sign-ins to open user usage logs.

Example logs from a sample Microsoft Azure instance

Shown above are two logins that appear to be failures. Under the "Authentication required" column, the first login says "Multi-factor authentication." Clicking on the row will pull up additional details about the login attempt.

Details on a non-interactive login from Jamf Connect via ROPG:

Under Authentication Details, the "Result detail" will let an administrator determine if the login was successful or a failure. In this example, the login was a success - the Result detail shows that the "User did not pass the MFA challenge (non-interactive)." This login can be interpreted in that the user was required to use MFA by either a Conditional Access policy or through Azure Multi-factor authentication.

In the second example, a user with MFA required failed to enter their correct password:

Details on a failed non-interactive login due to an incorrect password.

The Authentication required column shows "Single-factor authentication" and the Authentication Details show "Invalid username or password or Invalid on-premise username or password." While the user is required to use Multi-factor authentication, the user failed the first, single factor and thus was never prompted for MFA.

Creating a Custom Scope for Jamf Connect and Conditional Access policies

Workflow overview:

  • Create a “private endpoint” application registration with a custom API
    • With API permissions for "User.read"
    • With "Expose an API" scope created
    • Define roles like "Admin" and "Standard" for elevating macOS account permissions
  • Create a "public endpoint" application registration for OIDC to call that custom API
    • Remove API permissions for "User.read"
    • Add API permission for "My APIs" for the name of the application created in step one and the scope created in step one
  • Create an Azure Conditional Access policy to require multifactor authentication
    • Apply to application created in step one
  • Remove any CA policy applied to "All cloud apps" that would require MFA
  • Create a Jamf Connect Login configuration profile
    • Azure as Identity Provider
    • Define a custom scope
    • Define the Discovery URL for OIDC and ROPG
    • Test with Jamf Connect Configuration

Step One: Create an application registration with a custom API

Navigate to portal.azure.com → Azure Active Directory → App Registrations. Create a new app registration. Name the application something like "Jamf Connect - Conditional Access Policy API." Select the supported account types to "Accounts in this organizational directory only." Leave Redirect URI section blank. Register the application.

Application Registration Screen (as of 06DEC2021)

Navigate to API permissions on the left-hand navigation bar. Grant admin consent for the organization.

API permissions screen in Jamf Connect

Using the left-hand navigation bar, select "Expose an API." Set the Application ID URI. A default entry will be created based on the pattern of api://[application ID]. This may be modified if desired, but default entry is acceptable.

Jamf Connect expose an API screen

Select the option for "Add a scope."

Jamf Connect Expose an API, add a scope tab.

Set the scope name to jamfconnect. Set "Who can consent" to "Admins." Enter information into the Admin consent display name and Admin consent description. Any text is acceptable - this will be accepted by the admin in the next step. Press "Add scope" to save.

Jamf Connect add scope detail screen

Copy the scope with the Copy button and save it for later. This will be used as the OIDCScopes later in Jamf Connect Configuration.

Step Two: Create an application registration using this new API permission

Return to Azure Active Directory → App Registrations. Create a new app registration. Name the app "Jamf Connect - OIDC Endpoint." Set Supported account types to "Accounts in this organizational directory only." Set Redirect URI to "Public client/native (mobile & desktop)" with the value https://127.0.0.1/jamfconnect. Register the application.

Jamf Connect register and application screen

Navigate to API permissions. By default, the Microsoft Graph → User. Read permission is added. Use the ellipses to the right of Status to remove this permission from the application. Next, select "+ Add a permission."

Jamf Connect add permission screen

Select the "My APIs" tab. Select the name of the application you created in step one.

Jamf Connect request API permissions screen

Select the option for "Delegated permissions" and check the box for "jamfconnect" - the only permission listed in the application. Use the "Add permissions" button to close the window.

Jamf Connect add API permissions detail screen

Use the “Grant admin consent for [domain]” to grant permission to access the API on behalf of users.

Optional: Use the "App roles" option to add a role for "Administrator" and "Standard." This will allow you to define users or groups of users directly in Azure that should have administrator rights on macOS client machines. "App roles" is located on the left-hand navigation toolbar in the App registration. Refer to https://docs.jamf.com/jamf-connect/2.8.0/documentation/Login_Window_Preferences.html#ID-00007186 for more details on the OIDCAdminAttribute and OIDCAdmin settings for Jamf Connect.

Navigate to Overview. Record the Application (client) ID and the Directory (tenant) ID for later use with Jamf Connect Configuration.

Jamf Connect IODC Conditional Access screen

Navigate to Azure Active Directory → Enterprise Applications. Find the Jamf Connect - OIDC Endpoint application you created and assign users and roles to the application.

Step Three: Create an Azure Conditional Access policy

Navigate to portal.azure.com → Azure Conditional Access. Create a new policy.

Jamf Connect conditional access policies screen

Name the policy as desired. The sample will name the policy "Jamf Connect - Require Multifactor Authentication."

Jamf Connect new conditional access policy screen

Select "Users or workload identities." Select a test user to test your conditional access policy before applying to all users.

Jamf Connect new conditional access policy detail screen

Select "Cloud apps or actions." Select the Jamf Connect - Conditional Access Policy API you created in step one.

Jamf Connect new conditional access policy detail screen

Select "Grant." Check the option for "Require multi-factor authentication." Set Enable policy to "On" and "Create" to save the policy.

Jamf Connect new conditional access policy grant access screen

Step Four: Remove any Conditional Access policies applied to All cloud apps

Navigate to portal.azure.com → Azure Conditional Access. Examine any application applied to the scope of "All cloud apps." Either set "Enable policy" to "Off" for any application that has a grant of "Require multi-factor authentication" or modify the "Cloud apps or actions" to specifically list resources that should have MFA applied.

Applying a policy to require MFA for all cloud apps will cause the ROPG application in the next step to inaccurately show failed logins in the Azure sign-in logs.

Step Five: Create a Jamf Connect Configuration Profile

Use the Jamf Connect Configuration app included in the Jamf Connect software distribution disk image which you can download from account.jamf.com with your Jamf Nation credentials.

On the Identity Provider tab, set:

  • Identity Provider: Azure
  • OIDC Client ID: The application ID of the PUBLIC application you created in step two
  • ROPG Client ID: The same application ID
  • Scopes: Combine the scope you saved in step one with +openid+profile+email to look similar to: api://[RANDOM UUID STRING]/jamfconnect+openid+profile+email
  • Tenant: Enter the UUID of the tenant of your Azure instance. This can be found under the “Overview” tab of either of the app registrations made in step one or step two.
  • OIDC Redirect URI: (optional) Set to https://127.0.0.1/jamfconnect
  • Discovery URL: This can be found under the "Overview" tab of either of the app registrations from step one or step two under the "Endpoints" option. You can also manually create it by using the UUID of the tenant of your Azure instance in a format like the following:

    <a href="https://login.microsoftonline.com/">https://login.microsoftonline.com/</a>[TENANT UUID]/v2.0/.well-known/openid-configuration

screenshot of identity provider tab

OPTIONAL: If you want to define a role for users to be made administrators on a macOS client device, on the Login tab, set:

  • User Creation → Admin Roles: the value of the administrator App role you created in step two
  • User Creation → Admin Attribute: roles

On the Connect tab, set:

  • Authentication
    • ROPG Client ID: This should auto-populate from your entry on the Identity Provider screen
    • ROPG Tenant: The UUID of the Azure tenant
    • Discovery URL: THIS STEP IS ONLY REQUIRED FOR VERSIONS OF JAMF CONNECT PRIOR TO 2.12. Jamf Connect 2.12 and greater will send the appropriate endpoint request based on the discovery URL being either a V1 or V2 endpoint. The discovery URL does not need to be defined. This format is DIFFERENT from the Discovery URL from the Identity Provider tab. This can be found under the "Overview" tab of either of the app registrations from step one or step two under the "Endpoints" option for the V1 endpoint. You can also manually create it by using the UUID of the tenant of your Azure instance in a format like the following:

      <a href="https://login.microsoftonline.com/" title="https://login.microsoftonline.com/">https://login.microsoftonline.com/</a>[TENANT UUID]/.well-known/openid-configuration

      (note how the /v2.0 is missing from the URL.)

Test your configuration with the test user via OIDC. Make sure MFA was required.

Test your configuration with the test user via ROPG. Validate in the Azure portal under Azure Active Directory → Sign-in logs that the authentication was successful. Look for the Authentication Requirement to be "single-factor authentication." The Basic tab will show something like:

The Conditional Access tab should show that no policy was applied to the login.

Sean Rabbitt
Subscribe to the Jamf Blog

Have market trends, Apple updates and Jamf news delivered directly to your inbox.

To learn more about how we collect, use, disclose, transfer, and store your information, please visit our Privacy Policy.