{"id":5780,"date":"2025-01-15T09:07:21","date_gmt":"2025-01-15T07:07:21","guid":{"rendered":"https:\/\/www.msb365.blog\/?p=5780"},"modified":"2025-01-15T09:50:36","modified_gmt":"2025-01-15T07:50:36","slug":"unveiling-an-unexpected-behavior-in-conditionalaccess-unable-to-enforce-controls-for-some-apps","status":"publish","type":"post","link":"https:\/\/www.msb365.blog\/?p=5780","title":{"rendered":"Unveiling an unexpected behavior in ConditionalAccess: Unable to enforce controls for some Apps"},"content":{"rendered":"<p>Recently, an unexpected problem popped up with some ConditionalAccess policies: it is not possible to enforce controls. Applications show up as \u2018excluded\u2019 from the targeted resources when ConditionalAccess policies are evaluated. This behaviour allows users to access resources without MFA or compliant devices.<\/p>\n<p>This is possible for Applications which use Entra ID as Idp or require only minimum Microsoft Graph permissions (PublicClients: email, offline_access, openid, profile, User.Read, People.Read).<\/p>\n<p>In an article, Microsoft mentions a restriction for certain permissions, which could have something to do with this, but the actual behaviour seems to be quite random:<br \/>\n\u201cIn some cases, an\u00a0<strong>All resources (formerly \u2018All cloud apps\u2019)<\/strong>\u00a0policy could inadvertently block user access. These cases are excluded from policy enforcement and include.\u201d<\/p>\n<div class=\"vlp-link-container vlp-layout-basic\"><a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/identity\/conditional-access\/concept-conditional-access-cloud-apps#all-resources\" class=\"vlp-link\" title=\"Cloud apps, actions, and authentication context in Conditional Access policy - Microsoft Entra ID\" rel=\"nofollow\" target=\"_blank\"><\/a><div class=\"vlp-layout-zone-side\"><div class=\"vlp-block-2 vlp-link-image\"><img decoding=\"async\" src=\"https:\/\/learn.microsoft.com\/en-us\/media\/open-graph-image.png\" style=\"max-width: 150px; max-height: 150px\" \/><\/div><\/div><div class=\"vlp-layout-zone-main\"><div class=\"vlp-block-0 vlp-link-title\">Cloud apps, actions, and authentication context in Conditional Access policy - Microsoft Entra ID<\/div><div class=\"vlp-block-1 vlp-link-summary\">What are cloud apps, actions, and authentication context in a Microsoft Entra Conditional Access policy<\/div><\/div><\/div>\n<p>This post aims to bring more light on these cases and their implications for ConditionalAccess policy sets.<\/p>\n<p>\u00a0<\/p>\n<h3><strong>App registrations in Entra ID<\/strong><\/h3>\n<p>Before we start: App-Authentication can be configured for our App in Entra ID as \u201cWeb applications\u201d or \u201dMobile and desktop applications\u201d, whereat we have also different platform possibilities:<\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"alignnone size-full wp-image-5784\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi1.png\" alt=\"\" width=\"752\" height=\"410\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi1.png 752w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi1-300x164.png 300w\" sizes=\"(max-width: 752px) 100vw, 752px\" \/><\/p>\n<p>The connecting client can ether be public or confidential. The following blogpost describes the difference between the clients:<\/p>\n<div class=\"vlp-link-container vlp-layout-basic\"><a href=\"https:\/\/devblogs.microsoft.com\/identity\/public-v-confidential-clients\/\" class=\"vlp-link\" title=\"Public vs. confidential clients and how to avoid common security pitfalls in identity | Microsoft Entra Identity Platform\" rel=\"nofollow\" target=\"_blank\"><\/a><div class=\"vlp-layout-zone-side\"><div class=\"vlp-block-2 vlp-link-image\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/identity\/wp-content\/uploads\/sites\/74\/2023\/10\/developer_screens.png\" style=\"max-width: 150px; max-height: 150px\" \/><\/div><\/div><div class=\"vlp-layout-zone-main\"><div class=\"vlp-block-0 vlp-link-title\">Public vs. confidential clients and how to avoid common security pitfalls in identity | Microsoft Entra Identity Platform<\/div><div class=\"vlp-block-1 vlp-link-summary\">Learn about effective authentication practices and the distinctions between public and confidential clients. Plus tips on evading common pitfalls.<\/div><\/div><\/div>\n<p>\u00a0<\/p>\n<p>In my test I am authenticating as a public client to a test application called CodeGrant, which I created in my Tenant. The App uses delegated Microsoft Graph permissions which where consented by an administrator of the Tenant:<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-5785\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi2.png\" alt=\"\" width=\"752\" height=\"364\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi2.png 752w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi2-300x145.png 300w\" sizes=\"(max-width: 752px) 100vw, 752px\" \/><\/p>\n<p>When coming to the Authentication Settings of the App, Public client flows are not allowed and three platform configurations where added:<\/p>\n<ul>\n<li>Web<\/li>\n<li>Single-page application<\/li>\n<li>Mobile and desktop applications<\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<p>In these tests, the OAuth 2.0 auth code flow (without certificate or secret) is used by simple http requests, switching the platform with the redirect uri:<\/p>\n<p>https:\/\/login.microsoftonline.com\/06917a81-XXXX-XXXX-XXXX-XXXXXXXXXXXX\/oauth2\/v2.0\/authorize?client_id=f54384XX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&<strong>response_type=code<\/strong>&redirect_uri=<strong>XXXDefinedURLXXX<\/strong>&response_mode=query&scope=<strong>offline_access https:\/\/graph.microsoft.com\/user.read<\/strong>&state=XYZ5&prompt=select_account&code_challenge=XXXXXXXXX&code_challenge_method=S256<\/p>\n<p>The behavior for other OAuth flows is differs again. For reference about the used flow, you can check the Microsoft Learn article:<\/p>\n<div class=\"vlp-link-container vlp-layout-basic\"><a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/identity-platform\/v2-oauth2-auth-code-flow\" class=\"vlp-link\" title=\"Microsoft identity platform and OAuth 2.0 authorization code flow - Microsoft identity platform\" rel=\"nofollow\" target=\"_blank\"><\/a><div class=\"vlp-layout-zone-side\"><div class=\"vlp-block-2 vlp-link-image\"><img decoding=\"async\" src=\"https:\/\/learn.microsoft.com\/en-us\/media\/open-graph-image.png\" style=\"max-width: 150px; max-height: 150px\" \/><\/div><\/div><div class=\"vlp-layout-zone-main\"><div class=\"vlp-block-0 vlp-link-title\">Microsoft identity platform and OAuth 2.0 authorization code flow - Microsoft identity platform<\/div><div class=\"vlp-block-1 vlp-link-summary\">Protocol reference for the Microsoft identity platform\u2019s implementation of the OAuth 2.0 authorization code grant<\/div><\/div><\/div>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<h3><strong>A closer look at the behaviour<\/strong><\/h3>\n<p>When examining the issue, two behaviors were identified where different results of Conditional Access policy evaluation and enforcement would be expected:<\/p>\n<h4><strong><u>1 \u2013 Block or protect specific Access to specific App with ConditionalAccess Policy<\/u><\/strong><\/h4>\n<p>Upon integrating a third-party application into the Entra ID Tenant, we followed the consent procedure as outlined by the software provider. The objective was to restrict access to the application and its data under specific conditions, such as when the accessing user is not within the office. To achieve this, ConditionalAccess is used to restrict access to the application from Trusted Networks (could be also Global Secure Access):<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-5787\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi3.png\" alt=\"\" width=\"752\" height=\"620\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi3.png 752w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi3-300x247.png 300w\" sizes=\"(max-width: 752px) 100vw, 752px\" \/><\/p>\n<p>\u00a0<\/p>\n<p>The access to the app was not blocked as expected and when checking the SignIn-Logs<br \/>\nthe App is \u2018not included\u2019 even if in the policy configuration it is:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-5788\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi4.png\" alt=\"\" width=\"752\" height=\"231\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi4.png 752w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi4-300x92.png 300w\" sizes=\"(max-width: 752px) 100vw, 752px\" \/><\/p>\n<p>According to the article mentioned above, this could be interpreted as expected behaviour. Conditional Access is designed to protect resources (APIs) that are integrated with Entra ID and not applications. In this instance, since the user is not accessing any resources beyond the excluded scopes, Conditional Access policies are not enforced.<\/p>\n<p>It seems thatConditional Access <strong>cannot enforce controls<\/strong> for certain specific applications when no resources or only excluded resources within Microsoft 365 are used, such as when Entra ID is used as an Identity Provider.<\/p>\n<p>Until recently, it was generally understood that Conditional Access is applied to the applications in the Tenant and not just the resources behind them. Not sure if the renaming from \u201cAll cloud apps\u201d to \u201cAll resources\u201d was to address those wrong assumptions or if it was more than just a simple renaming and the policy enforcement behaviour changed.<\/p>\n<p>Following this finding, it is advisable to verify whether any application is protected with MFA or compliant device enforcement with CA-Policies targeted to all applications.<\/p>\n<p>\u00a0<\/p>\n<h4><strong><u>2 \u2013 Protect all Applications with ConditionalAccess<\/u><\/strong><\/h4>\n<p>Upon further inspection, it is observed that not all authentications to an application connected to Entra ID are consistently protected by Conditional Access Policies, even when these policies are targeted to \u201cAll resources\u201d (previously referred to as \u2018All cloud apps\u2019). In some instances, access was granted without requiring a compliant device or multi-factor authentication (MFA).<\/p>\n<p>A closer analysis revealed that Conditional Access policies may exclude specific applications for various reasons, such as the exclusion of any resource from a policy.<\/p>\n<p>To illustrate this, a standard policy was created targeting all resources and client app types, necessitating either a compliant device, app protection, or MFA. The policy excludes one target resource, in this case \u201cReport phishing\u201d, but it could be <strong>ANY<\/strong> <strong>Resource<\/strong>.<\/p>\n<p>This discrepancy highlights the necessity for thorough verification of Conditional Access policies, ensuring that applications expected to be protected are indeed subject to the intended security measures.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-5790\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi5.png\" alt=\"\" width=\"752\" height=\"649\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi5.png 752w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi5-300x259.png 300w\" sizes=\"(max-width: 752px) 100vw, 752px\" \/><\/p>\n<p>\u00a0<\/p>\n<p>The Policy can have different user assignments, conditions or grant controls, the behaviour stays the same.<\/p>\n<p>The application used in this tests has three platforms configurations for authentication:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-5791\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi6.png\" alt=\"\" width=\"752\" height=\"599\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi6.png 752w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi6-300x239.png 300w\" sizes=\"(max-width: 752px) 100vw, 752px\" \/><\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>Upon conducting the tests, it was anticipated that the Conditional Access policy would uniformly enforce multi-factor authentication (MFA) or require a compliant device\/app for all authentication attempts. However, analysis revealed inconsistencies. Specifically, during two out of three authentication attempts, an authorization code was obtained and utilized with single-factor authentication, bypassing the expected MFA challenges or device compliance requirements.<\/p>\n<p>When analysing the SignIn Logs, the App assignment is not matched and the App shows up as \u201cApp excluded\u201d for these authentications.<\/p>\n<table>\n<tbody>\n<tr>\n<td width=\"179\"><strong>Application platform<\/strong><\/td>\n<td width=\"246\"><strong>Result<\/strong><\/td>\n<td width=\"176\"><strong>Reason<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"179\"><strong>Mobile and desktop applications<\/strong><\/td>\n<td width=\"246\">CA Policy not applied<\/td>\n<td width=\"176\">App excluded<\/td>\n<\/tr>\n<tr>\n<td width=\"179\"><strong>Single-page application<\/strong><\/td>\n<td width=\"246\">CA Policy not applied<\/td>\n<td width=\"176\">App excluded<\/td>\n<\/tr>\n<tr>\n<td width=\"179\"><strong>Web<\/strong><\/td>\n<td width=\"246\">Require multifactor authentication<\/td>\n<td width=\"176\">All apps included<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u00a0<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-5792\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi7.png\" alt=\"\" width=\"752\" height=\"201\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi7.png 752w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi7-300x80.png 300w\" sizes=\"(max-width: 752px) 100vw, 752px\" \/><\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>The only request, where the Policy was enforced correctly, requiring MFA was the one to the Web platform:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-5793\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi8.png\" alt=\"\" width=\"602\" height=\"830\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi8.png 602w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi8-218x300.png 218w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/p>\n<p>\u00a0<\/p>\n<p>When testing further, the excluded resources where excluded, so that the CA policy now appears as follows:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-5795\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi9.png\" alt=\"\" width=\"587\" height=\"797\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi9.png 587w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi9-221x300.png 221w\" sizes=\"(max-width: 587px) 100vw, 587px\" \/><\/p>\n<p>\u00a0<\/p>\n<p>When making the identical authentication requests as before the results are different, but finally as expected:<\/p>\n<table>\n<tbody>\n<tr>\n<td width=\"179\"><strong>Application platform<\/strong><\/td>\n<td width=\"246\"><strong>Result<\/strong><\/td>\n<td width=\"176\"><strong>Reason<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"179\"><strong>Mobile and desktop applications<\/strong><\/td>\n<td width=\"246\">Require multifactor authentication<\/td>\n<td width=\"176\">All apps included<\/td>\n<\/tr>\n<tr>\n<td width=\"179\"><strong>Single-page application<\/strong><\/td>\n<td width=\"246\">Require multifactor authentication<\/td>\n<td width=\"176\">All apps included<\/td>\n<\/tr>\n<tr>\n<td width=\"179\"><strong>Web<\/strong><\/td>\n<td width=\"246\">Require multifactor authentication<\/td>\n<td width=\"176\">All apps included<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u00a0<\/p>\n<p>After that result I did other tests, excluding completely random Apps from the policy, getting always the same result: the Policy is applied only to the Web platform, not covering \u201cSingle-page application\u201d & \u201cMobile apps and desktop clients\u201d authentication platform.<\/p>\n<p>Further tests where done, excluding completely random applications from the policy, which repeatedly yielded the same result: The policy consistently applies only to the Web platform, while it does not cover the \u201cSingle-page application\u201d (SPA) and \u201cMobile apps and desktop clients\u201d authentication platforms.<\/p>\n<p>\u00a0<\/p>\n<h3><strong>Conclusion<\/strong><\/h3>\n<p>This inconsistency poses a significant challenge for ensuring the security of applications, especially for third-party integrations where Entra ID is used as Idp.<\/p>\n<p>The consequence of this behavior extend to Zero Trust and Secure Access Service Edge (SASE) implementations. Until an app is configured with the platform \u201cMobile and desktop applications\u201d or \u201cSPA\u201d and doesn\u2019t access other resources within Microsoft 365, ConditionalAccess is not enforcing controls such as compliant devices, networks (including GSA), or even blocking specific users from accessing certain apps. This limitation undermines the effectiveness of Zero Trust and SASE strategies, which rely on robust access controls to secure applications and data.<\/p>\n<p>\u00a0<\/p>\n<h3><strong>Author<\/strong><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-5800\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi_.png\" alt=\"\" width=\"315\" height=\"851\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi_.png 315w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2025\/01\/Hilpi_-111x300.png 111w\" sizes=\"(max-width: 315px) 100vw, 315px\" \/><\/p>\n<p>\u00a0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, an unexpected problem popped up with some ConditionalAccess policies: it is not possible to enforce controls. Applications show up as \u2018excluded\u2019 from the targeted resources when ConditionalAccess policies are evaluated. This behaviour allows users to access resources without MFA or compliant devices. This is possible for Applications which use Entra ID as Idp or [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":5781,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[12,1923],"tags":[1773,2003,2000,2004],"class_list":["post-5780","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-microsoft-365","tag-azure","tag-conditionalaccess","tag-entraid","tag-microsoft365"],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/posts\/5780","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5780"}],"version-history":[{"count":12,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/posts\/5780\/revisions"}],"predecessor-version":[{"id":5809,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/posts\/5780\/revisions\/5809"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/media\/5781"}],"wp:attachment":[{"href":"https:\/\/www.msb365.blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5780"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5780"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5780"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}