Conditional Access target resources
Microsoft's edit ·
Microsoft's commit message in MicrosoftDocs/entra-docs · commit a7f838a · +1 −225 lines · also on GitHub
⋯ 139 unchanged lines
140140
### Legacy Conditional Access behavior when an ALL resources policy has a resource exclusion
141141
142142
> [!WARNING]
143
−> [The following Conditional Access behavior is changing](https://aka.ms/CAAllResourcesWithExclusionsChange). Those low privileged scopes that were previously excluded from policy enforcement will **no longer be excluded**. This change means that users who were previously able to access the application without any Conditional Access enforcement might now receive Conditional Access challenges. The change is rolling out in phases starting in March, 2026.
143
+> [The following Conditional Access behavior is changing](https://aka.ms/CAAllResourcesWithExclusionsChange). Those low privileged scopes that were previously excluded from policy enforcement will **no longer be excluded**. This change means that users who were previously able to access the application without any Conditional Access enforcement might now receive Conditional Access challenges. The change is rolling out in phases starting in March, 2026. For more information see [Enforcement for baseline scopes](concept-enforcement-resource-exclusions.md).
144144
145145
If any app is excluded from the policy, to avoid inadvertently blocking user access, certain low privilege scopes were *previously* excluded from policy enforcement. These scopes allowed calls to the underlying Graph APIs, like `Windows Azure Active Directory` (00000002-0000-0000-c000-000000000000) and `Microsoft Graph` (00000003-0000-0000-c000-000000000000), to access user profile and group membership information commonly used by applications as part of authentication. For example: when Outlook requests a token for Exchange, it also asks for the `User.Read` scope to be able to display the basic account information of the current user.
146146
⋯ 17 unchanged lines
164164
> [!NOTE]
165165
> The [Azure AD Graph retirement](https://techcommunity.microsoft.com/blog/microsoft-entra-blog/important-update-azure-ad-graph-retirement/4364990) does not affect the Azure AD Graph (Windows Azure Active Directory) resource registered in your tenant.
166166
167
−### User experience
168
−
169
−In user sign-in flows where client applications request only the scopes listed above, users might now receive Conditional Access challenges (such as MFA or device compliance). The exact challenge depends on the access controls configured in your policies that target All resources (with or without resource exclusions) or policies that explicitly target Azure AD Graph.
170
−
171
−In the following example, the tenant has a Conditional Access policy with the following details:
172
−- Targeting All users and All resources
173
−- Resource exclusions for a confidential client application and Exchange Online
174
−- MFA is configured as the grant control
175
−
176
−#### Example scenarios
177
−
178
−| Example scenario | User impact (before → after) | Conditional Access evaluation |
179
−|---|---|---|
180
−| A user signs into Visual Studio Code desktop client, which requests openid and profile scopes. | **Before**: User not prompted for MFA</br>**After**: User is prompted for MFA | Conditional Access is now evaluated using Windows Azure Active Directory as the enforcement audience. |
181
−| A user signs in using Azure CLI, which requests only `User.Read`. | **Before**: User not prompted for MFA</br>**After**: User is prompted for MFA | Conditional Access is now evaluated using Windows Azure Active Directory as the enforcement audience. |
182
−| A user signs in through a confidential client application (excluded from the policy) that requests only `User.Read` and `People.Read`. | **Before**: User not prompted for MFA</br>**After**: User is prompted for MFA | Conditional Access is now evaluated using Windows Azure Active Directory as the enforcement audience. |
183
−
184
−There is no change in behavior when a client application requests a scope beyond those listed previously, as illustrated in the following examples.
185
−
186
−#### Example scenarios
187
−
188
−| Example scenario | User impact | Conditional Access evaluation |
189
−|---|---|---|
190
−| A user signs in to a confidential client application (excluded from the policy) that requests offline_access and SharePoint access (`Files.Read`). | No change in behavior | Conditional Access continues to be enforced based on the SharePoint resource. |
191
−| A user signs in to the OneDrive desktop sync client. OneDrive requests offline_access and Exchange Online access (`Mail.Read`). | No change in behavior | Conditional Access is not enforced because Exchange Online is excluded from the policy. |
192
−
193
−Most applications request scopes beyond the previously listed scopes and are already subject to Conditional Access enforcement, unless the application is explicitly excluded from the policy. In such cases, there is no change in behavior.
194
−
195
−Custom applications that are intentionally designed to request only the previously listed scopes and are not designed to handle Conditional Access challenges might need to be updated so that they can handle Conditional Access challenges. Refer to the [Microsoft Conditional Access developer guidance](../../identity-platform/v2-conditional-access-dev-guide.md) for implementation details.
196
−
197
−### How to identify applications affected by the low-privilege scope enforcement change
198
−
199
−Applications can be pre-authorized to request only one or more of the previously listed scopes. Use the following options to identify affected applications.
200
−
201
−#### [PowerShell](#tab/powershell)
202
−
203
−Use the following PowerShell script to list all applications in your tenant that are pre-authorized to request only one or more of the scopes that are affected by this change.
204
−
205
−> [!NOTE]
206
−> Applications can request additional scopes dynamically (with admin consent). This script will not identify such applications.
207
−
208
−```powershell
209
−# ==============================
210
−# Inventory of apps whose delegated consent grants include ONLY
211
−# the OIDC scopes + specific directory scopes listed below.
212
−#
213
−# Enhancements incorporated:
214
−# - Supported both PowerShell 5.1 and 7.x
215
−# - Add user sign-in count (last 7 days) per app
216
−#
217
−# Output:
218
−# - ServicePrincipalObjectId (oauth2PermissionGrants.clientId = SP object id)
219
−# - AppId
220
−# - AppDisplayName
221
−# - AppOwnerOrganizationId (for classification)
222
−# - Scopes (union of delegated scopes granted)
223
−# - UserSigninsLast7Days (Successful + Failed)
224
−# ==============================
225
−
226
−$TenantId = Read-Host "Enter your Microsoft Entra tenant ID (GUID)"
227
−
228
−$BaselineScopes = @(
229
− "openid", "profile", "email", "offline_access",
230
− "User.Read", "User.Read.All", "User.ReadBasic.All",
231
− "People.Read", "People.Read.All",
232
− "GroupMember.Read.All", "Member.Read.Hidden"
233
−)
234
−
235
−Disconnect-MgGraph -ErrorAction SilentlyContinue
236
−
237
−Connect-MgGraph -TenantId $TenantId -Scopes @(
238
− "DelegatedPermissionGrant.Read.All",
239
− "Directory.Read.All",
240
− "Reports.Read.All"
241
−)
242
−
243
−# ------------------------------
244
−# Pull oauth2PermissionGrants (paging)
245
−# ------------------------------
246
−$uri = "https://graph.microsoft.com/beta/oauth2PermissionGrants?`$select=clientId,scope,consentType"
247
−$grants = @()
248
−while ($uri) {
249
− $resp = Invoke-MgGraphRequest -Method GET -Uri $uri
250
− $grants += $resp.value
251
− $uri = $resp.'@odata.nextLink'
252
−}
253
−
254
−# ------------------------------
255
−# Build baseline-only candidate set (Jun: HashSet per clientId)
256
−# ------------------------------
257
−$scopesByClient = @{} # key: clientId (SP objectId), value: HashSet[string] (case-insensitive)
258
−
259
−foreach ($g in $grants) {
260
− $cid = $g.clientId.ToString().Trim()
261
− if (-not $cid) { continue }
262
−
263
− if (-not $scopesByClient.ContainsKey($cid)) {
264
− $scopesByClient[$cid] = [System.Collections.Generic.HashSet[string]]::new(
265
− [System.StringComparer]::OrdinalIgnoreCase
266
− )
267
− }
268
−
269
− foreach ($s in ($g.scope -split '\s+')) {
270
− if ($s -and $s.Trim().Length -gt 0) {
271
− [void]$scopesByClient[$cid].Add($s.Trim())
272
− }
273
− }
274
−}
275
−
276
−$candidates = foreach ($cid in $scopesByClient.Keys) {
277
− $scopes = $scopesByClient[$cid]
278
− if ($scopes.Count -le 0) { continue }
279
−
280
− $outside = $scopes | Where-Object { $_ -notin $BaselineScopes }
281
− if ($outside.Count -eq 0) {
282
− [PSCustomObject]@{
283
− ServicePrincipalObjectId = $cid
284
− Scopes = ($scopes -join ' ')
285
− }
286
− }
287
−}
288
−
289
−# ------------------------------
290
−# Pull per-app sign-in summary for last 7 days (Graph REST via Invoke-MgGraphRequest)
291
−# Endpoint: GET /beta/reports/getAzureADApplicationSignInSummary(period='D7')
292
−# In this API output, 'id' corresponds to the appId (clientId)
293
−# ------------------------------
294
−$signInSummary = @()
295
−$signInUri = "https://graph.microsoft.com/beta/reports/getAzureADApplicationSignInSummary(period='D7')"
296
−
297
−while ($signInUri) {
298
− $resp = Invoke-MgGraphRequest -Method GET -Uri $signInUri
299
−
300
− if ($resp -and $resp.value) {
301
− $signInSummary += $resp.value
302
− }
303
−
304
− # Paging (if present)
305
− $signInUri = $resp.'@odata.nextLink'
306
−}
307
−
308
−# appId -> total sign-ins (7d)
309
−$signInCountByAppId = @{}
310
−foreach ($s in $signInSummary) {
311
− $appId = $s.id
312
− if (-not $appId) { continue }
313
−
314
− # PS5.1-safe null handling
315
− $success = 0
316
− $failed = 0
317
− if ($null -ne $s.successfulSignInCount) { $success = [int]$s.successfulSignInCount }
318
− if ($null -ne $s.failedSignInCount) { $failed = [int]$s.failedSignInCount }
319
−
320
− $signInCountByAppId[$appId] = $success + $failed
321
−}
322
−
323
−$resultsTenantOwned = @()
324
−$resultsNotTenantOwned = @()
325
−
326
−# ------------------------------
327
−# Filter to tenant-owned or external apps; enrich with appId/displayName + sign-in counts
328
−# ------------------------------
329
−foreach ($c in $candidates) {
330
− try {
331
− $spUri = "https://graph.microsoft.com/beta/servicePrincipals/$($c.ServicePrincipalObjectId)?`$select=id,appId,displayName,appOwnerOrganizationId"
332
− $sp = Invoke-MgGraphRequest -Method GET -Uri $spUri
333
−
334
− $signinCount7d = 0
335
− if ($sp.appId -and $signInCountByAppId.ContainsKey($sp.appId)) {
336
− $signinCount7d = $signInCountByAppId[$sp.appId]
337
− }
338
−
339
− $row = [PSCustomObject]@{
340
− ServicePrincipalObjectId = $c.ServicePrincipalObjectId
341
− AppId = $sp.appId
342
− AppDisplayName = $sp.displayName
343
− AppOwnerOrganizationId = $sp.appOwnerOrganizationId
344
− Scopes = $c.Scopes
345
− UserSigninsLast7Days = $signinCount7d
346
− }
347
−
348
− if ($sp.appOwnerOrganizationId -eq $TenantId) {
349
− $resultsTenantOwned += $row
350
− }
351
− else {
352
− $resultsNotTenantOwned += $row
353
− }
354
− }
355
− catch {
356
− # Ignore non-enumerable / missing service principals
357
− }
358
−}
359
−
360
−# ------------------------------
361
−# Output
362
−# ------------------------------
363
−'=== Tenant-owned apps whose delegated consent grants include ONLY baseline scopes + user sign-ins (last 7 days) ==='
364
−$resultsTenantOwned |
365
− Sort-Object UserSigninsLast7Days -Descending |
366
− Format-Table -AutoSize
367
−
368
−'=== External apps whose delegated consent grants include ONLY baseline scopes + user sign-ins (last 7 days) ==='
369
−$resultsNotTenantOwned |
370
− Sort-Object UserSigninsLast7Days -Descending |
371
− Format-Table -AutoSize
372
−```
373
−
374
−#### [Usage and Insights report](#tab/usage-and-insights-report)
375
−
376
−The [Usage and Insights report in Microsoft Entra](../monitoring-health/concept-usage-insights-report.md) can help monitor application sign-in activity for specific applications.
377
−
378
−1. Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com) as at least a [Reports Reader](../role-based-access-control/permissions-reference.md#reports-reader).
379
−1. Browse to **Entra ID** > **Monitoring & health** > **Usage & insights**.
380
−1. Select an application > select **Usage & insights**.
381
−
382
−#### [Sign-in logs](#tab/sign-in-logs)
383
−
384
−Microsoft Entra ID sign-in logs can also provide a detailed list of sign-ins for specific applications.
385
−
386
−1. Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com) as at least a [Reports Reader](../role-based-access-control/permissions-reference.md#reports-reader).
387
−1. Browse to **Entra ID** > **Monitoring & health** > **Sign-in logs**.
388
−1. Set the filter **Application** and enter the application name or application ID as the value.
389
−
390
−---
391167
392168
### Protect directory information
393169
⋯ 101 unchanged lines
Microsoft's Markdown source from MicrosoftDocs/entra-docs, © Microsoft Corporation, under MIT. Changed lines with up to 3 unchanged lines around each; ChangeIntel kept this copy 10 Oct 04:32 UTC. The commit date is when the source changed, which can be hours or days before Learn published it.