Troubleshoot Microsoft 365 Sign-in Issues with Conditional Access PowerShell

Disclaimer: Some content in this article may be AI-generated and might not be fully accurate. Please double-check any critical information, or reach out to us if you have questions or find any issues.

Users calling with "I can't sign into Office 365" or "I'm getting blocked from my email" usually means Conditional Access policies are doing their job—but sometimes they're blocking legitimate access. PowerShell gives you the tools to diagnose what's happening and why.

TL;DR

  • Connect: Connect-AzureAD and Connect-MgGraph
  • Check policies: Get-AzureADMSConditionalAccessPolicy
  • User status: Get-MgUser -UserId [email protected]
  • Sign-in logs: Get-MgAuditLogSignIn
  • Device info: Get-MgDevice for registered devices
  • Common fixes: Add to emergency access, exclude from policy

Connect to Required Services

You need both Azure AD and Microsoft Graph connections:

# Azure AD (for Conditional Access policies)
Connect-AzureAD

# Microsoft Graph (for sign-in logs and user info)
Connect-MgGraph -Scopes "AuditLog.Read.All", "Directory.Read.All", "User.Read.All"

Check Conditional Access Policies

List all Conditional Access policies:

Get-AzureADMSConditionalAccessPolicy | Select-Object DisplayName, State, Id

Get detailed information about a specific policy:

Get-AzureADMSConditionalAccessPolicy -PolicyId "policy-guid" | ConvertTo-Json -Depth 5

Check which policies apply to a user:

$user = Get-MgUser -UserId "[email protected]"
$policies = Get-AzureADMSConditionalAccessPolicy

foreach ($policy in $policies) {
    if ($policy.Conditions.Users.IncludeUsers -contains $user.Id -or 
        $policy.Conditions.Users.IncludeGroups -contains (Get-MgUserMemberOf -UserId $user.Id).Id) {
        Write-Host "Policy $($policy.DisplayName) applies to $($user.DisplayName)"
    }
}

Check Recent Sign-in Attempts

Get the last 10 sign-in attempts for a user:

Get-MgAuditLogSignIn -Filter "userPrincipalName eq '[email protected]'" -Top 10 | 
Select-Object CreatedDateTime, UserPrincipalName, Status, IpAddress, Location, DeviceDetail, ConditionalAccessStatus

Check for failures in the last 24 hours:

$startDate = (Get-Date).AddDays(-1)
Get-MgAuditLogSignIn -Filter "createdDateTime ge $($startDate.ToString('yyyy-MM-ddTHH:mm:ssZ')) and status/errorCode ne 0" -Top 50 | 
Select-Object CreatedDateTime, UserPrincipalName, @{Name="Error";Expression={$_.Status.ErrorCode}}, @{Name="Description";Expression={$_.Status.FailureReason}}

Common Conditional Access Errors

Error: "Your sign-in was blocked by Conditional Access"

Check what policies are blocking:

$signin = Get-MgAuditLogSignIn -Filter "userPrincipalName eq '[email protected]'" -Top 1
$signin.AppliedConditionalAccessPolicies | Where-Object {$_.Result -eq "failure"}

Error: "Device not compliant" or "Device not registered"

Check device registration status:

Get-MgDevice -Filter "displayName eq 'USER-LAPTOP'" | Select-Object DisplayName, IsCompliant, IsManaged, ApproximateLastSignInDateTime

Find all devices for a user:

$user = Get-MgUser -UserId "[email protected]"
Get-MgUserOwnedDevice -UserId $user.Id | Select-Object DisplayName, OperatingSystem, OperatingSystemVersion

Check User Account Status

Verify user account is not blocked:

Get-MgUser -UserId "[email protected]" | Select-Object DisplayName, UserPrincipalName, AccountEnabled, UserType

Check for password expiration or MFA issues:

Get-MgUser -UserId "[email protected]" | Select-Object DisplayName, PasswordPolicies, StrongAuthenticationRequirements

Temporarily Exclude User from Policy

For emergency access, exclude a user from a specific policy:

$policy = Get-AzureADMSConditionalAccessPolicy -PolicyId "policy-guid"
$policy.Conditions.Users.ExcludeUsers += "user-guid"
Update-AzureADMSConditionalAccessPolicy -PolicyId $policy.Id -Conditions $policy.Conditions

Create an emergency access policy:

$emergencyPolicy = New-Object -TypeName Microsoft.Open.MSGraph.Model.AzureADMSConditionalAccessPolicy
$emergencyPolicy.DisplayName = "Emergency Access - $((Get-Date).ToString('yyyy-MM-dd'))"
$emergencyPolicy.State = "enabled"
$emergencyPolicy.Conditions.Users.IncludeUsers = @("emergency-user-guid")
$emergencyPolicy.Conditions.Applications.IncludeApplications = @("All")
$emergencyPolicy.GrantControls.BuiltInControls = @("block")
$emergencyPolicy.GrantControls.Operator = "OR"

New-AzureADMSConditionalAccessPolicy -Policy $emergencyPolicy

Check Location and IP Restrictions

See what locations are blocked/allowed:

Get-AzureADMSNamedLocationPolicy | Select-Object DisplayName, IpRanges, CountriesAndRegions

Check if a user's IP is in a blocked location:

$userSignIns = Get-MgAuditLogSignIn -Filter "userPrincipalName eq '[email protected]'" -Top 5
foreach ($signin in $userSignIns) {
    Write-Host "IP: $($signin.IpAddress) - Location: $($signin.Location.City), $($signin.Location.CountryOrRegion)"
}

Application-Specific Issues

Check which apps are affected by Conditional Access:

$policies = Get-AzureADMSConditionalAccessPolicy
foreach ($policy in $policies) {
    if ($policy.State -eq "enabled") {
        Write-Host "Policy: $($policy.DisplayName)"
        Write-Host "Apps: $($policy.Conditions.Applications.IncludeApplications)"
        Write-Host "---"
    }
}

Check for app-specific sign-in issues:

Get-MgAuditLogSignIn -Filter "userPrincipalName eq '[email protected]' and appId eq '1fec8e78-bce4-4aaf-ab1b-5451cc387264'" -Top 5

Bulk User Analysis

Find all users affected by failed sign-ins in the last 24 hours:

$startDate = (Get-Date).AddDays(-1)
$failedSignIns = Get-MgAuditLogSignIn -Filter "createdDateTime ge $($startDate.ToString('yyyy-MM-ddTHH:mm:ssZ')) and status/errorCode ne 0" -Top 100

$failedUsers = $failedSignIns | Group-Object UserPrincipalName | 
Select-Object Name, Count, @{Name="LatestError";Expression={($_.Group | Sort-Object CreatedDateTime -Descending | Select-Object -First 1).Status.FailureReason}}

$failedUsers | Sort-Object Count -Descending | Format-Table

Disable Conditional Access Temporarily

For emergency access, disable all policies (use with extreme caution):

# List all enabled policies
Get-AzureADMSConditionalAccessPolicy | Where-Object {$_.State -eq "enabled"} | Select-Object DisplayName, Id

# Disable a specific policy
Update-AzureADMSConditionalAccessPolicy -PolicyId "policy-guid" -State "disabled"

# Re-enable when done
Update-AzureADMSConditionalAccessPolicy -PolicyId "policy-guid" -State "enabled"

Export Configuration for Documentation

Create a report of all Conditional Access policies:

$policies = Get-AzureADMSConditionalAccessPolicy
$report = @()

foreach ($policy in $policies) {
    $report += [PSCustomObject]@{
        Name = $policy.DisplayName
        State = $policy.State
        UsersIncluded = $policy.Conditions.Users.IncludeUsers.Count
        GroupsIncluded = $policy.Conditions.Users.IncludeGroups.Count
        Applications = $policy.Conditions.Applications.IncludeApplications -join "; "
        GrantControls = $policy.GrantControls.BuiltInControls -join "; "
    }
}

$report | Export-Csv "C:\Temp\ConditionalAccessPolicies.csv" -NoTypeInformation

Best Practices

  • Test policies: Always test with a test account before applying broadly
  • Use emergency access accounts: Have break-glass accounts excluded from all policies
  • Monitor sign-ins: Regularly review failed sign-in attempts
  • Document policies: Keep clear documentation of what each policy does
  • Use groups wisely: Put users in groups rather than listing individuals

Quick Reference

# Connect
Connect-AzureAD
Connect-MgGraph -Scopes "AuditLog.Read.All", "Directory.Read.All"

# List policies
Get-AzureADMSConditionalAccessPolicy | Select DisplayName, State

# Check user sign-ins
Get-MgAuditLogSignIn -Filter "userPrincipalName eq '[email protected]'" -Top 5

# Find blocking policies
Get-MgAuditLogSignIn -Filter "userPrincipalName eq '[email protected]'" -Top 1 | 
Select-Object -ExpandProperty AppliedConditionalAccessPolicies | 
Where-Object {$_.Result -eq "failure"}

# Temporarily exclude user
$policy = Get-AzureADMSConditionalAccessPolicy -PolicyId "guid"
$policy.Conditions.Users.ExcludeUsers += "user-guid"
Update-AzureADMSConditionalAccessPolicy -PolicyId $policy.Id -Conditions $policy.Conditions

Conditional Access is powerful but can be frustrating when it blocks legitimate access. The key is having the right PowerShell commands to quickly diagnose what's happening and provide targeted solutions rather than disabling security entirely.

Need Help with Microsoft 365 Access Issues?

Conditional Access policies and sign-in troubleshooting can be complex and time-sensitive. My company NHM Ohio provides rapid response Microsoft 365 support to diagnose and resolve access issues before they impact your business.

Whether you need emergency access restoration, policy configuration, or ongoing monitoring, explore our Microsoft 365 services or contact us for immediate assistance.