Intermediate โฑ 90 min ๐Ÿ“‹ 10 Steps

Configure Entra ID Protection & Risk-Based Policies

Enable Microsoft Entra ID Protection, configure user risk and sign-in risk policies, set up Conditional Access with risk-based controls, investigate risky users and sign-ins, integrate with Defender XDR, and automate remediation for compromised identities.

๐Ÿ“‹ Overview

About This Lab

Entra ID Protection uses Microsoft’s global identity intelligence to detect identity-based risks in real time. It identifies leaked credentials, impossible travel, anonymous IP usage, and suspicious sign-in patterns, then enables automated response through risk-based Conditional Access policies.

๐Ÿข Enterprise Use Case

An enterprise with 20,000 users and hybrid identity detects 50+ risky sign-ins daily. Manual investigation takes 30 minutes per event. They need automated risk-based policies that block high-risk sign-ins and force MFA for medium-risk, reducing mean time to respond from hours to seconds.

๐ŸŽฏ What You Will Learn

  1. Navigate the Entra ID Protection dashboard
  2. Configure user risk policy
  3. Configure sign-in risk policy
  4. Create risk-based Conditional Access policies
  5. Investigate risky users and risky sign-ins
  6. Configure risk remediation (self-service password reset, MFA)
  7. Integrate with Defender XDR incidents
  8. Query risk data via Microsoft Graph API
  9. Create monitoring workbooks
  10. Establish operational procedures

๐Ÿ”‘ Why This Matters

Identity is the new perimeter. 80% of breaches involve compromised credentials. Manual investigation of risky sign-ins doesn’t scale. Automated risk-based policies ensure compromised accounts are contained in seconds, not hours.

โš™๏ธ Prerequisites

  • Microsoft Entra ID P2 license. required for Identity Protection features and risk-based Conditional Access
  • Security Administrator role. to configure Identity Protection policies
  • Conditional Access Administrator role. to create and manage Conditional Access policies
  • Global Reader role. minimum for viewing risk reports and dashboards
  • Test user accounts. at least two test accounts for validating risk policies
  • Microsoft Graph PowerShell SDK. installed for automation and API queries
๐Ÿ’ก Pro Tip: Use dedicated test accounts for policy validation. Never test risk-based block policies against your own admin account. you could lock yourself out. Create accounts like risk-test-user@contoso.com and exclude your break-glass accounts from all risk policies.

Step 1 ยท Navigate to Entra ID Protection

Start by exploring the Entra ID Protection dashboard to understand the current risk landscape in your tenant. The dashboard provides an at-a-glance view of risky users, risky sign-ins, and risk detections.

Portal Instructions

  1. Navigate to entra.microsoft.com > Protection > Identity Protection
  2. Review the Overview dashboard. note the summary tiles for risky users, risky sign-ins, and risk detections
  3. Click Risky users in the left menu. review the list of users flagged with risk levels (High, Medium, Low)
  4. Click Risky sign-ins. review sign-ins flagged with risk detections
  5. Click Risk detections. review individual detection events (leaked credentials, anonymous IP, impossible travel, etc.)
  6. Note the Risk state column: At risk, Confirmed compromised, Dismissed, Remediated

Connect via PowerShell

# Install the Microsoft Graph PowerShell SDK (if not already installed)
Install-Module Microsoft.Graph -Scope CurrentUser -Force

# Connect to Microsoft Graph with required scopes
# WHAT: Authenticates to Graph API with permissions needed for Identity Protection
# WHY: Each scope grants specific access:
#   IdentityRiskyUser.Read.All   - Read all risky user data (risk level, state, history)
#   IdentityRiskEvent.Read.All   - Read risk detection events (leaked creds, anon IP, etc.)
#   Policy.Read.All              - Read Conditional Access policies
#   Policy.ReadWrite.ConditionalAccess - Create/modify CA policies
Connect-MgGraph -Scopes "IdentityRiskyUser.Read.All","IdentityRiskEvent.Read.All","Policy.Read.All","Policy.ReadWrite.ConditionalAccess"

# Verify connection - confirms the authenticated account, tenant, and granted scopes
Get-MgContext | Select-Object Account, TenantId, Scopes

# List current risky users filtered to high risk level
# OUTPUT fields:
#   RiskLevel - none | low | medium | high | hidden (aggregated risk across all detections)
#   RiskState - atRisk | confirmedCompromised | remediated | dismissed | unknownFutureValue
#   RiskLastUpdatedDateTime - when the risk level was last recalculated
Get-MgRiskyUser -Filter "riskLevel eq 'high'" | Select-Object UserDisplayName, UserPrincipalName, RiskLevel, RiskState, RiskLastUpdatedDateTime

# List the 10 most recent risk detections sorted by detection time
# OUTPUT fields:
#   RiskEventType - e.g. leakedCredentials, anonymizedIPAddress, impossibleTravel,
#                   unfamiliarFeatures, malwareInfectedIPAddress, passwordSpray
#   RiskLevel - low | medium | high (severity of this individual detection)
#   IpAddress - source IP of the risky sign-in (useful for threat intel correlation)
Get-MgRiskDetection -Top 10 -OrderBy "detectedDateTime desc" | Select-Object UserDisplayName, RiskEventType, RiskLevel, DetectedDateTime, IpAddress
๐Ÿ’ก Pro Tip: Bookmark the Identity Protection dashboard URL. As a security admin, you should check this daily. Pay special attention to any users whose risk state is “At risk” with a High risk level. these require immediate investigation.

Step 2 ยท Configure User Risk Policy

The user risk policy evaluates the aggregate risk associated with a user account. When a user is determined to be at risk (e.g., leaked credentials detected), this policy forces a secure password change at next sign-in.

Portal Instructions

  1. Navigate to Entra admin center > Protection > Conditional Access > Policies
  2. Click + New policy
  3. Name: CA-UserRisk-RequirePasswordChange
  4. Assignments > Users: All users (exclude break-glass accounts)
  5. Assignments > Target resources: All cloud apps
  6. Conditions > User risk > Configure: Yes > select High
  7. Grant > Grant access > check Require password change
  8. Session > Sign-in frequency: Every time
  9. Enable policy: Report-only (start in report-only, then switch to On after validation)
  10. Click Create

PowerShell: Create User Risk Policy

# WHAT: Create a Conditional Access policy that forces password change for high-risk users
# WHY: When Entra ID Protection detects a user's credentials are likely compromised
#      (e.g., leaked credentials found on dark web), this policy forces a secure password
#      reset at the next sign-in, automatically remediating the risk
$params = @{
    DisplayName = "CA-UserRisk-RequirePasswordChange"
    # State values: enabled | disabled | enabledForReportingButNotEnforced (report-only)
    # IMPORTANT: Always start in report-only mode to assess impact before enforcing
    State       = "enabledForReportingButNotEnforced"
    Conditions  = @{
        Users = @{
            IncludeUsers = @("All")
            # CRITICAL: Always exclude break-glass accounts to prevent lockout
            ExcludeUsers = @("<break-glass-account-object-id>")
        }
        Applications = @{
            IncludeApplications = @("All")  # Apply to all cloud apps
        }
        # UserRiskLevels: low | medium | high
        # User risk = offline/aggregated risk (leaked creds, threat intel)
        # Unlike sign-in risk, user risk persists until remediated
        UserRiskLevels = @("high")
    }
    GrantControls = @{
        Operator        = "OR"
        # BuiltInControls options: block, mfa, compliantDevice,
        #   domainJoinedDevice, approvedApplication, passwordChange
        BuiltInControls = @("passwordChange")
    }
    SessionControls = @{
        SignInFrequency = @{
            Value     = 0
            Type      = "everyTime"  # Forces re-authentication every time
            IsEnabled = $true
        }
    }
}

New-MgIdentityConditionalAccessPolicy -BodyParameter $params

# Verify the policy was created and check its enforcement state
Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'CA-UserRisk-RequirePasswordChange'" | Select-Object DisplayName, State
โš ๏ธ Important: Always start Conditional Access policies in Report-only mode. Monitor the Conditional Access insights workbook for 1–2 weeks to understand the impact before switching to On. A misconfigured user risk policy can lock out legitimate users who triggered a false positive risk detection.

Step 3 ยท Configure Sign-In Risk Policy

The sign-in risk policy evaluates each sign-in attempt in real time. It detects anomalies such as anonymous IP addresses, impossible travel, unfamiliar sign-in properties, and password spray attacks, then requires MFA or blocks the sign-in.

Portal Instructions

  1. Navigate to Entra admin center > Protection > Conditional Access > Policies
  2. Click + New policy
  3. Name: CA-SignInRisk-RequireMFA
  4. Assignments > Users: All users (exclude break-glass accounts)
  5. Assignments > Target resources: All cloud apps
  6. Conditions > Sign-in risk > Configure: Yes > select High and Medium
  7. Grant > Grant access > check Require multifactor authentication
  8. Enable policy: Report-only
  9. Click Create

PowerShell: Create Sign-In Risk Policy

# WHAT: Create a CA policy requiring MFA for medium and high sign-in risk
# WHY: Sign-in risk is evaluated in REAL TIME during each authentication.
#   Unlike user risk (offline/aggregated), sign-in risk detects anomalies
#   in the current session: anonymous IP, impossible travel, password spray, etc.
# SignInRiskLevels: low | medium | high
#   medium = suspicious but not confirmed (e.g., unfamiliar sign-in properties)
#   high   = strong indicators of compromise (e.g., anonymous IP + atypical travel)
$signInRiskPolicy = @{
    DisplayName = "CA-SignInRisk-RequireMFA"
    State       = "enabledForReportingButNotEnforced"
    Conditions  = @{
        Users = @{
            IncludeUsers = @("All")
            ExcludeUsers = @("<break-glass-account-object-id>")
        }
        Applications = @{
            IncludeApplications = @("All")
        }
        SignInRiskLevels = @("high", "medium")
    }
    GrantControls = @{
        Operator        = "OR"
        # Requires step-up MFA - user must complete additional authentication
        BuiltInControls = @("mfa")
    }
}

New-MgIdentityConditionalAccessPolicy -BodyParameter $signInRiskPolicy

# WHAT: Create a BLOCK policy for high-risk sign-ins only
# WHY: Layered defence - high-risk sign-ins are fully blocked (no MFA bypass)
#   while medium-risk sign-ins can proceed if user satisfies MFA
# NOTE: Deploy this AFTER validating false positive rates on the MFA policy above
$blockHighRisk = @{
    DisplayName = "CA-SignInRisk-BlockHighRisk"
    State       = "enabledForReportingButNotEnforced"
    Conditions  = @{
        Users = @{
            IncludeUsers = @("All")
            ExcludeUsers = @("<break-glass-account-object-id>")
        }
        Applications = @{
            IncludeApplications = @("All")
        }
        SignInRiskLevels = @("high")
    }
    GrantControls = @{
        Operator        = "OR"
        BuiltInControls = @("block")  # Completely blocks the sign-in attempt
    }
}

New-MgIdentityConditionalAccessPolicy -BodyParameter $blockHighRisk

# Verify: List all Conditional Access policies with "Risk" in their name
# OUTPUT: DisplayName and State (enabled, disabled, or report-only)
Get-MgIdentityConditionalAccessPolicy | Where-Object { $_.DisplayName -like "*Risk*" } | Select-Object DisplayName, State
๐Ÿ’ก Pro Tip: Use a layered approach: require MFA for medium+high sign-in risk, and block for high risk only after validating false positive rates. This gives you defence in depth. medium-risk sign-ins can still proceed if the user satisfies MFA, while confirmed high-risk sign-ins are fully blocked.

Step 4 ยท Create Risk-Based Conditional Access Policies

Combine user risk, sign-in risk, device compliance, and named locations into comprehensive Conditional Access policies that adapt to the threat context of each authentication.

Portal Instructions

  1. Navigate to Entra admin center > Protection > Conditional Access > Named locations
  2. Click + IP ranges location. add your corporate IP ranges as Corporate-Network and mark as Trusted
  3. Navigate to Policies > + New policy
  4. Name: CA-Combined-RiskPolicy-CorpApps
  5. Users: All users (exclude break-glass accounts)
  6. Target resources: Select specific sensitive apps (e.g., Azure Portal, Exchange Online, SharePoint Online)
  7. Conditions:
    • User risk: High, Medium
    • Sign-in risk: High, Medium
    • Locations: Exclude trusted Corporate-Network
  8. Grant: Require MFA + Require compliant device (require all selected controls)
  9. Session: Sign-in frequency = 1 hour
  10. Enable: Report-only

Example Policy JSON (Microsoft Graph)

# Combined risk-based Conditional Access policy via Graph API
$combinedPolicy = @{
    DisplayName = "CA-Combined-RiskPolicy-CorpApps"
    State       = "enabledForReportingButNotEnforced"
    Conditions  = @{
        Users = @{
            IncludeUsers = @("All")
            ExcludeUsers = @("<break-glass-object-id-1>", "<break-glass-object-id-2>")
        }
        Applications = @{
            IncludeApplications = @(
                "797f4846-ba00-4fd7-ba43-dac1f8f63013"  # Azure Management
                "00000002-0000-0ff1-ce00-000000000000"  # Exchange Online
                "00000003-0000-0ff1-ce00-000000000000"  # SharePoint Online
            )
        }
        UserRiskLevels   = @("high", "medium")
        SignInRiskLevels = @("high", "medium")
        Locations = @{
            IncludeLocations = @("All")
            ExcludeLocations = @("<corporate-named-location-id>")
        }
    }
    GrantControls = @{
        Operator        = "AND"
        BuiltInControls = @("mfa", "compliantDevice")
    }
    SessionControls = @{
        SignInFrequency = @{
            Value     = 1
            Type      = "hours"
            IsEnabled = $true
        }
    }
}

New-MgIdentityConditionalAccessPolicy -BodyParameter $combinedPolicy
๐Ÿ’ก Pro Tip: Named locations with the Trusted flag reduce sign-in risk scores for authentication from those IPs. Define your corporate egress IPs, VPN ranges, and branch office IPs as trusted locations to avoid flooding your SOC with false positive alerts for legitimate corporate users.

Step 5 ยท Investigate Risky Users

When Identity Protection flags a user as risky, investigate the risk history timeline to determine whether the user is truly compromised or if the detection is a false positive.

Portal Investigation

  1. Navigate to Entra admin center > Protection > Identity Protection > Risky users
  2. Filter by Risk level: High
  3. Click on a user to open their risk detail panel
  4. Review the Risk history timeline. each entry shows the detection type, risk level, and timestamp
  5. Click on individual detections to see details: IP address, location, device info, sign-in correlation ID
  6. Based on your investigation, take action:
    • Confirm user compromised. sets user risk to High and triggers risk policies
    • Dismiss user risk. clears the risk (use for confirmed false positives)
    • Reset password. forces a password change and clears user risk
    • Block user. immediately blocks all sign-ins

PowerShell: Query & Manage Risky Users

# Get all high-risk users
$riskyUsers = Get-MgRiskyUser -Filter "riskLevel eq 'high'" -All
$riskyUsers | Select-Object UserDisplayName, UserPrincipalName, RiskLevel, RiskState, RiskDetail, RiskLastUpdatedDateTime | Format-Table -AutoSize

# Get risk history for a specific user
$userId = (Get-MgRiskyUser -Filter "userPrincipalName eq 'john.doe@contoso.com'").Id
Get-MgRiskyUserHistory -RiskyUserId $userId | Select-Object RiskLevel, RiskState, RiskDetail, InitiatedBy, @{N='DetectedDateTime';E={$_.Activity.RiskEventTypes}} | Format-Table

# Confirm a user is compromised (sets risk to High)
Confirm-MgRiskyUserCompromised -UserIds @($userId)

# Dismiss risk for a false positive
Invoke-MgDismissRiskyUser -UserIds @($userId)

# Bulk export risky users to CSV
Get-MgRiskyUser -All | Select-Object UserDisplayName, UserPrincipalName, RiskLevel, RiskState, RiskLastUpdatedDateTime | Export-Csv -Path "RiskyUsers-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
๐Ÿ’ก Pro Tip: Don’t blindly dismiss all risks. Investigate the risk history first. A dismissed risk clears the user’s risk state, which also prevents risk-based Conditional Access from triggering. If the user truly is compromised, dismissing the risk removes your safety net.

Step 6 ยท Investigate Risky Sign-Ins

Risky sign-ins are individual authentication events where Identity Protection detected a risk signal. Investigate these to understand the specific threat context and correlate with Defender XDR incidents.

Portal Investigation

  1. Navigate to Entra admin center > Protection > Identity Protection > Risky sign-ins
  2. Filter by Risk detection type:
    • Anonymous IP address. sign-in from Tor exit nodes / anonymous VPN
    • Impossible travel. sign-ins from geographically distant locations too quickly
    • Unfamiliar sign-in properties. new device, browser, or location
    • Password spray. many accounts targeted with common passwords
    • Leaked credentials. user credentials found on the dark web
    • Malicious IP address. sign-in from known malicious IPs
  3. Click a risky sign-in to review: IP address, location, device details, app used, and risk detection details
  4. Cross-reference with Defender XDR: open security.microsoft.com > Incidents and search for the same user

KQL: Query Sign-In & Risk Logs

// Risky sign-ins from the last 7 days
SigninLogs
| where TimeGenerated > ago(7d)
| where RiskLevelDuringSignIn in ("high", "medium")
| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress,
    LocationDetails, RiskLevelDuringSignIn, RiskEventTypes_V2,
    DeviceDetail, ConditionalAccessStatus
| order by TimeGenerated desc

// Sign-ins from anonymous IP addresses
SigninLogs
| where TimeGenerated > ago(7d)
| where RiskEventTypes_V2 has "anonymizedIPAddress"
| project TimeGenerated, UserPrincipalName, IPAddress,
    LocationDetails, AppDisplayName, ResultType
| order by TimeGenerated desc

// Impossible travel detections
SigninLogs
| where TimeGenerated > ago(7d)
| where RiskEventTypes_V2 has "impossibleTravel"
| project TimeGenerated, UserPrincipalName, IPAddress,
    LocationDetails, DeviceDetail
| order by TimeGenerated desc

// Correlate risky sign-ins with AADRiskyUsers
let riskySignIns = SigninLogs
| where TimeGenerated > ago(24h)
| where RiskLevelDuringSignIn in ("high", "medium")
| distinct UserPrincipalName;
AADRiskyUsers
| where UserPrincipalName in (riskySignIns)
| project UserPrincipalName, RiskLevel, RiskState, RiskDetail, RiskLastUpdatedDateTime
โš ๏ธ Important: The RiskEventTypes_V2 field in SigninLogs contains the risk detection types as a JSON array. Use the has operator (not ==) to filter for specific risk types. Common values: anonymizedIPAddress, impossibleTravel, unfamiliarFeatures, leakedCredentials, passwordSpray.

Step 7 ยท Configure Self-Service Remediation

Enable users to self-remediate their own risk by performing MFA and changing their password through Self-Service Password Reset (SSPR). This removes the SOC burden for low-to-medium risk events while maintaining security.

Enable SSPR for Risk Remediation

  1. Navigate to Entra admin center > Protection > Password reset
  2. Set Self-service password reset enabled: All (or target a pilot group first)
  3. Under Authentication methods, require at least 2 methods (e.g., Authenticator app + phone)
  4. Navigate to Protection > Authentication methods > Policies
  5. Verify Microsoft Authenticator is enabled and configured for push notifications
  6. Under Registration, set Require users to register when signing in: Yes

Test the Self-Service Remediation Flow

  1. Using PowerShell, confirm the test user as compromised to trigger user risk:
# Confirm test user as compromised to trigger risk policies
$testUserId = (Get-MgUser -Filter "userPrincipalName eq 'risk-test-user@contoso.com'").Id
Confirm-MgRiskyUserCompromised -UserIds @($testUserId)

# Verify the user is now flagged as high risk
Get-MgRiskyUser -Filter "userPrincipalName eq 'risk-test-user@contoso.com'" | Select-Object UserDisplayName, RiskLevel, RiskState
  1. Open an InPrivate browser and sign in as risk-test-user@contoso.com
  2. The user risk policy should trigger: the user is prompted to change their password
  3. After the password change, verify the user’s risk state is now Remediated
# Verify risk was cleared after self-remediation
Get-MgRiskyUser -Filter "userPrincipalName eq 'risk-test-user@contoso.com'" | Select-Object UserDisplayName, RiskLevel, RiskState, RiskDetail

# Expected output:
# RiskLevel: none
# RiskState: remediated
# RiskDetail: userPerformedSecuredPasswordChange
๐Ÿ’ก Pro Tip: Self-service remediation only works if the user has registered MFA and SSPR methods before the risk event. Ensure all users are required to register authentication methods during onboarding. Users who haven’t registered will be blocked. not prompted to remediate. which generates helpdesk tickets.

Step 8 ยท Integrate with Defender XDR

Entra ID Protection risk signals feed directly into Microsoft Defender XDR incidents. This integration provides SOC analysts with a unified view of identity risk alongside endpoint, email, and cloud app signals.

Portal Instructions

  1. Navigate to security.microsoft.com > Incidents
  2. Filter by Service source > Microsoft Entra ID Protection
  3. Open an incident containing Identity Protection alerts
  4. Review the Evidence and response tab. note user entities with risk information
  5. Check the Attack story to see how identity risk correlates with other signals (endpoint alerts, email alerts)
  6. Use Advanced hunting for cross-product correlation queries

KQL: Cross-Signal Correlation Queries

// Correlate Entra ID risky sign-ins with endpoint logon events
let riskyUsers = AADSignInEventsBeta
| where TimeGenerated > ago(24h)
| where RiskLevelDuringSignIn in ("high", "medium")
| distinct AccountUpn;
IdentityLogonEvents
| where TimeGenerated > ago(24h)
| where AccountUpn in (riskyUsers)
| project TimeGenerated, AccountUpn, DeviceName, LogonType,
    Application, Protocol, ActionType
| order by TimeGenerated desc

// Join Identity Protection risk events with endpoint alerts
let riskyAccounts = AADRiskyUsers
| where RiskLevel in ("high", "medium")
| project UserPrincipalName, RiskLevel, RiskState;
AlertEvidence
| where TimeGenerated > ago(7d)
| where EntityType == "User"
| where RemediationStatus != "Resolved"
| join kind=inner riskyAccounts on $left.AccountUpn == $right.UserPrincipalName
| project TimeGenerated, Title, AccountUpn, RiskLevel, Severity

// Find users with both identity risk and suspicious mailbox activity
let riskyIds = AADRiskyUsers
| where RiskLevel == "high"
| project UserPrincipalName;
EmailEvents
| where TimeGenerated > ago(24h)
| where SenderFromAddress in (riskyIds) or RecipientEmailAddress in (riskyIds)
| where DeliveryAction == "Delivered"
| project TimeGenerated, SenderFromAddress, RecipientEmailAddress, Subject, DeliveryAction
๐Ÿ’ก Pro Tip: Defender XDR automatically correlates Identity Protection alerts with other product alerts into unified incidents. A leaked credential detection (Identity Protection) + suspicious inbox rule (MDO) + malware download (MDE) on the same user = a single correlated incident showing the full attack chain.

Step 9 ยท Monitor with Workbooks & Alerts

Create Azure Monitor alerts for high-risk detections and build Sentinel workbook tiles for ongoing identity risk monitoring and trend analysis.

Create Azure Monitor Alert Rule

  1. Navigate to Azure Portal > Monitor > Alerts > + Create > Alert rule
  2. Scope: your Log Analytics workspace
  3. Condition: Custom log search
  4. Use the following query and set threshold to > 0:
// Alert: High-risk user detected in the last 15 minutes
SigninLogs
| where TimeGenerated > ago(15m)
| where RiskLevelAggregated == "high"
| summarize Count=count() by UserPrincipalName, RiskLevelAggregated
| where Count > 0
  1. Evaluation frequency: Every 5 minutes
  2. Actions: notify SOC via email and Teams
  3. Severity: Sev 1

KQL: Workbook Tiles for Risk Trends

// Tile 1: Risk Detection Trend (30 days)
SigninLogs
| where TimeGenerated > ago(30d)
| where RiskLevelDuringSignIn in ("high", "medium", "low")
| summarize RiskCount=count() by bin(TimeGenerated, 1d), RiskLevelDuringSignIn
| render timechart

// Tile 2: Top Risk Detection Types
SigninLogs
| where TimeGenerated > ago(30d)
| where RiskEventTypes_V2 != "[]"
| mv-expand RiskType = parse_json(RiskEventTypes_V2)
| summarize Count=count() by tostring(RiskType)
| top 10 by Count
| render barchart

// Tile 3: Risky User Trends (30 days)
AADRiskyUsers
| summarize
    HighRisk=countif(RiskLevel == "high"),
    MediumRisk=countif(RiskLevel == "medium"),
    LowRisk=countif(RiskLevel == "low")

// Tile 4: Risk Remediation Effectiveness
SigninLogs
| where TimeGenerated > ago(30d)
| where RiskLevelDuringSignIn in ("high", "medium")
| summarize
    TotalRisky=count(),
    MFASatisfied=countif(AuthenticationRequirement == "multiFactorAuthentication"
        and ResultType == "0"),
    Blocked=countif(ResultType == "53003"),
    PasswordChanged=countif(ResultType == "50097")
| extend RemediationRate = round(todouble(MFASatisfied + Blocked + PasswordChanged) / TotalRisky * 100, 1)

// Tile 5: Geographic Distribution of Risky Sign-Ins
SigninLogs
| where TimeGenerated > ago(30d)
| where RiskLevelDuringSignIn in ("high", "medium")
| extend City = tostring(LocationDetails.city),
         Country = tostring(LocationDetails.countryOrRegion)
| summarize Count=count() by Country, City
| top 20 by Count
| render barchart

Deploy the Workbook

  1. Navigate to Microsoft Sentinel > Workbooks > Add workbook
  2. Click Edit > Advanced Editor
  3. Add each query above as a separate tile with appropriate visualisation (timechart, barchart, table, stat tile)
  4. Add parameter filters: TimeRange, RiskLevel, UserPrincipalName
  5. Save as Entra ID Protection. Risk Dashboard
  6. Pin to your SOC’s shared dashboard
๐Ÿ’ก Pro Tip: Track the Remediation Rate tile weekly. A healthy tenant should show >90% of risky sign-ins being mitigated (MFA satisfied, blocked, or password changed). If the rate is low, you have gaps in policy coverage or users who haven’t registered MFA.

Step 10 ยท Clean Up & Next Steps

Review your Identity Protection configuration, disable test policies, and plan your ongoing operational procedures.

What You Accomplished

  1. User Risk Policy. requires password change for high-risk users
  2. Sign-In Risk Policy. requires MFA for medium+high risk sign-ins
  3. Combined Policy. requires MFA + compliant device for risky access to sensitive apps
  4. Self-Service Remediation. SSPR enabled for user-driven risk clearing
  5. Defender XDR Integration. identity risk in unified incidents
  6. Monitoring. Azure Monitor alerts + Sentinel workbook for risk trends

Disable Test Policies

# List all risk-related Conditional Access policies
Get-MgIdentityConditionalAccessPolicy | Where-Object { $_.DisplayName -like "*Risk*" } | Select-Object Id, DisplayName, State | Format-Table

# Disable test policies (set to Report-only or Off)
$testPolicies = Get-MgIdentityConditionalAccessPolicy | Where-Object { $_.DisplayName -like "*Risk*" -and $_.State -eq "enabledForReportingButNotEnforced" }
foreach ($policy in $testPolicies) {
    # To disable (off): Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id -State "disabled"
    Write-Host "Policy: $($policy.DisplayName). State: $($policy.State)"
}

# Dismiss risk for test users
$testUserId = (Get-MgUser -Filter "userPrincipalName eq 'risk-test-user@contoso.com'").Id
Invoke-MgDismissRiskyUser -UserIds @($testUserId)

# Disconnect Graph session
Disconnect-MgGraph

Operational Procedures

  • Daily: Review the Identity Protection dashboard for new high-risk users and sign-ins
  • Weekly: Investigate and triage all unresolved medium-risk detections
  • Monthly: Review Conditional Access policy insights reports; tune false positive rates
  • Quarterly: Review all dismissed risks to identify recurring patterns; update named locations

Next Steps

๐Ÿ’ก Pro Tip: After validating in report-only mode, transition policies to On in this order: sign-in risk (MFA) first (lower user impact), then user risk (password change), then the combined policy. Monitor helpdesk ticket volume after each enablement. a spike in password reset requests or MFA complaints signals you need to tune exclusions or named locations.

๐Ÿ“š Documentation Resources

ResourceDescription
Entra ID Protection overviewFeature overview and architecture
Configure risk policiesStep-by-step guide for user risk and sign-in risk policies
Investigate riskHow to investigate risky users and sign-ins
Conditional Access overviewPolicy framework for adaptive access control
Risk detection typesComplete reference of all risk detection types and descriptions
Microsoft Graph Identity Protection APIsProgrammatic access to risk data via Graph API
Remediate risks and unblock usersSelf-service and admin remediation workflows
Identity Protection workbooksBuilt-in workbooks for risk monitoring and analysis
← All Labs Next Lab →