private/entra/Get-EntraUserMfaStatus.ps1
function Get-EntraUserMfaStatus { <# .SYNOPSIS Get the MFA user(s) status from Microsoft Entra. .DESCRIPTION Retrieve if the user(s) is protected by MFA. .PARAMETER UserPrincipalName (Optional) The Entra user principal name. .EXAMPLE Get-EntraUserMfaStatus; #> [cmdletbinding()] [OutputType([pscustomobject[]])] param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$UserPrincipalName ) BEGIN { # Write to log. $customProgress = Write-CustomProgress -Activity $MyInvocation.MyCommand.Name -CurrentOperation 'Get Entra user(s) MFA status'; # If user principal name is null. if ([string]::IsNullOrEmpty($UserPrincipalName)) { # Get all users. $entraUsers = Get-EntraUser -All; # Get all MFA user states. $mfaStates = Get-EntraUserMfaState; } else { # Get all users. $entraUsers = Get-EntraUser | Where-Object { $_.UserPrincipalName -eq $UserPrincipalName }; # Get all MFA user states. $mfaStates = Get-EntraUserMfaState -Id $entraUsers.Id; } # Get all Entra conditional access policy members. $conditionalAccessPolicyMembers = Get-EntraConditionalAccessPolicyMember; # Get all Entra conditional access policies that require MFA. $conditionalAccessMfaPolicies = Get-EntraConditionalAccessPolicyMfa; # Get all Entra applications. $entraApplications = Get-EntraApplication -All; # Result object. $users = @(); } PROCESS { # Write to log. Write-CustomLog -Message ('Found {0} Entra users' -f $entraUsers.Count) -Level 'Verbose'; # Foreach Entra user. foreach ($entraUser in $entraUsers) { # Add user to result. $user = [PSCustomObject]@{ UserPrincipalName = $entraUser.UserPrincipalName; DisplayName = $entraUser.DisplayName; AccountEnabled = $entraUser.accountEnabled; AccountType = $entraUser.userType; FullMfa = $false; PartialMfa = $false; ConditionalAccessPolicy = @(); PerUserMfaState = ''; IsMfaCapable = $false; IsMfaRegistered = $false; IsAdmin = $false; Apps = @(); TargetAllApps = $false; }; # User conditional access policies. $userConditionalAccessPolicies = @(); # User conditional access policies that require MFA. $userConditionalAccessMfaPolicies = @(); # User MFA state. $userMfaState = $null; # Foreach conditional access policies that the user is a member of. foreach ($conditionalAccessPolicyMember in $conditionalAccessPolicyMembers) { # If the user is a member of the conditional access policy. if ($entraUser.UserPrincipalName -in $conditionalAccessPolicyMember.TargetedUsers) { # Add conditional access policy. $userConditionalAccessPolicies += $conditionalAccessPolicyMember; } } # Foreach user conditional access. foreach ($userConditionalAccessPolicy in $userConditionalAccessPolicies) { # Foreach conditional access policies that require MFA. foreach ($conditionalAccessMfaPolicy in $conditionalAccessMfaPolicies) { # If the two conditional access policies are not the same. if ($userConditionalAccessPolicy.Id -ne $conditionalAccessMfaPolicy.Id) { # Continue to next policy that require MFA. continue; } # Add conditional access policy. $userConditionalAccessMfaPolicies += $conditionalAccessMfaPolicy; } } # Foreach MFA user state. foreach ($mfaState in $mfaStates) { # If the user is protected by MFA. if ($entraUser.UserPrincipalName -eq $mfaState.UserPrincipalName) { # Set user MFA state. $userMfaState = $mfaState; } } # Set MFA state. if ($null -ne $userMfaState) { # Set properties. $user.PerUserMfaState = $userMfaState.PerUserMfaState; $user.IsMfaCapable = $userMfaState.IsMfaCapable; $user.IsMfaRegistered = $userMfaState.IsMfaRegistered; $user.IsAdmin = $userMfaState.IsAdmin; } # Foreach user conditional access policies that require MFA. foreach ($userConditionalAccessMfaPolicy in $userConditionalAccessMfaPolicies) { # If the policy is not enabled. if ($userConditionalAccessMfaPolicy.State -eq 'disabled') { # Continue to next policy that require MFA. continue; } # Add conditional access policy. $user.ConditionalAccessPolicy += $userConditionalAccessMfaPolicy.Name; # If all apps are targeted. if ($true -eq $userConditionalAccessMfaPolicy.AllApps) { # Set target all apps. $user.TargetAllApps = $true; } # Foreach app. foreach ($app in $userConditionalAccessMfaPolicy.Apps) { # If the app is a GUID. if ($true -eq (Test-Guid -InputObject $app)) { # Get application by id. $application = $entraApplications | Where-Object { $_.AppId -eq $app }; # Add app. $user.Apps += $application.DisplayName; } # Else built-in app. else { # Add app. $user.Apps += $app; } } # If MFA or AuthenticationStrength is required. if ($true -eq $userConditionalAccessMfaPolicy.MFA -or $true -eq $userConditionalAccessMfaPolicy.AuthenticationStrength) { # Set user conditional access require MFA. $user.PartialMfa = $true; } # If policy requires MFA and is target all apps. if (($true -eq $userConditionalAccessMfaPolicy.MFA -or $true -eq $userConditionalAccessMfaPolicy.AuthenticationStrength) -and $true -eq $userConditionalAccessMfaPolicy.AllApps) { # Set user conditional access require MFA. $user.FullMfa = $true; } } # Remove target apps duplicates. $user.Apps = $user.Apps | Select-Object -Unique; # If the user is not protected by MFA. if ($false -eq $user.FullMfa) { # Write to log. Write-CustomLog -Message ("User '{0}'' is not protected by MFA in all apps" -f $user.UserPrincipalName) -Level 'Verbose'; } # Add user to result. $users += $user; } } END { # Write to log. Write-CustomProgress @customProgress; # Return result. return $users; } } |