Update-UserMFA.ps1


<#PSScriptInfo
 
.VERSION 0.1
 
.GUID 499fcb19-e02b-4f3e-80b8-1013c2fce966
 
.AUTHOR jmcarthur@roundrocktexas.gov
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>


#Requires -Module AzureAD

<#
 
.DESCRIPTION
 Script utilizing WPF forms to update MFA status of specified user.
 
#>
 

Param()

$WarningPreference = "SilentlyContinue"

Function Invoke-InputBox {

    [cmdletbinding(DefaultParameterSetName="plain")]
    [OutputType([system.string],ParameterSetName='plain')]
    [OutputType([system.security.securestring],ParameterSetName='secure')]

    Param(
        [Parameter(ParameterSetName="secure")]
        [Parameter(HelpMessage = "Enter the title for the input box. No more than 25 characters.",
        ParameterSetName="plain")]        

        [ValidateNotNullorEmpty()]
        [ValidateScript({$_.length -le 25})]
        [string]$Title = "Update MFA Status",

        [Parameter(ParameterSetName="secure")]        
        [Parameter(HelpMessage = "Enter a prompt. No more than 50 characters.",ParameterSetName="plain")]
        [ValidateNotNullorEmpty()]
        [ValidateScript({$_.length -le 50})]
        [string]$Prompt = "Target user's email address:",
        
        [Parameter(HelpMessage = "Use to mask the entry and return a secure string.",
        ParameterSetName="secure")]
        [switch]$AsSecureString
    )

    if ($PSEdition -eq 'Core') {
        Write-Warning "Sorry. This command will not run on PowerShell Core."
        #bail out
        Return
    }

    Add-Type -AssemblyName PresentationFramework
    Add-Type �assemblyName PresentationCore
    Add-Type �assemblyName WindowsBase

    #remove the variable because it might get cached in the ISE or VS Code
    Remove-Variable -Name myInput -Scope script -ErrorAction SilentlyContinue

    $form = New-Object System.Windows.Window
    $stack = New-object System.Windows.Controls.StackPanel

    #define what it looks like
    $form.Title = $title
    $form.Height = 150
    $form.Width = 350

    $label = New-Object System.Windows.Controls.Label
    $label.Content = " $Prompt"
    $label.HorizontalAlignment = "left"
    $stack.AddChild($label)

    if ($AsSecureString) {
        $inputbox = New-Object System.Windows.Controls.PasswordBox
    }
    else {
        $inputbox = New-Object System.Windows.Controls.TextBox
    }

    $inputbox.Width = 300
    $inputbox.HorizontalAlignment = "center"

    $stack.AddChild($inputbox)

    $space = new-object System.Windows.Controls.Label
    $space.Height = 10
    $stack.AddChild($space)

    $btn = New-Object System.Windows.Controls.Button
    $btn.Content = "_OK"

    $btn.Width = 65
    $btn.HorizontalAlignment = "center"
    $btn.VerticalAlignment = "bottom"

    #add an event handler
    $btn.Add_click( {
            if ($AsSecureString) {
                $script:myInput = $inputbox.SecurePassword
            }
            else {
                $script:myInput = $inputbox.text
            }
            $form.Close()
        })
    $btn.IsDefault = $true

    $stack.AddChild($btn)
    $space2 = new-object System.Windows.Controls.Label
    $space2.Height = 10
    $stack.AddChild($space2)

    $btn2 = New-Object System.Windows.Controls.Button
    $btn2.Content = "_Cancel"

    $btn2.Width = 65
    $btn2.HorizontalAlignment = "center"
    $btn2.VerticalAlignment = "bottom"

    #add an event handler
    $btn2.Add_click( {
            $form.Close()
        })

    $stack.AddChild($btn2)

    #add the stack to the form
    $form.AddChild($stack)

    #show the form
    $inputbox.Focus() | Out-Null
    $form.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen

    $form.ShowDialog() | out-null

    #write the result from the input box back to the pipeline
    $script:myInput
}

Function Invoke-SelectionBox {


    Param(
    [Parameter(Mandatory=$true)]$user
    )

    if ($PSEdition -eq 'Core') {
        Write-Warning "Sorry. This command will not run on PowerShell Core."
        #bail out
        Return
    }

    Add-Type -AssemblyName PresentationFramework
    Add-Type �assemblyName PresentationCore
    Add-Type �assemblyName WindowsBase

    #remove the variable because it might get cached in the ISE or VS Code
    Remove-Variable -Name myInput -Scope script -ErrorAction SilentlyContinue

    #check that $user has necessary properties to continue
    if (-not ($user.DisplayName))
    {
        Write-Warning "The provided user does not have the required properties."
        Return
    }
    elseif  (-not $user.StrongAuthenticationRequirements)
    {
        # this is a new user who's MFA has never been configured
        $name = $user.DisplayName.ToString()
        $str = $($name + "'s MFA has not been enabled.")
        $notEnabled = $true
    }
    else
    {
        $name = $user.DisplayName.ToString()
        $state = $user.StrongAuthenticationRequirements.State.ToString()
        $str = $($name + "'s MFA status is " + $state)
    }

    $form = New-Object System.Windows.Window
    $stack = New-object System.Windows.Controls.StackPanel

    #define what it looks like
    $form.Title = "Update MFA Status"
    $form.Height = if ($notEnabled) {175} else {150}
    $form.Width = 350

    $label = New-Object System.Windows.Controls.Label
    $label.Content = " $str"
    $label.HorizontalAlignment = "left"
    $stack.AddChild($label)
    
    # build options and outputs based on MFA state
    if ($state -eq "Enforced") 
    {
        $opt1 = "Enabled"
        $opt2 = "Disabled"
    } 
    elseif ($state -eq "Disabled")
    {
        $opt1 = "Enabled"
        $opt2 = "Enforced"
    }
    elseif ($notEnabled)
    {
        $opt1 = "Enabled"
        $opt2 = "Enforced"
        $opt3 = "Cancel"
    } 
    else
    {
        $opt1 = "Enforced"
        $opt2 = "Disabled"
    }

    #region BUTTON1
    $space = new-object System.Windows.Controls.Label
    $space.Height = 10
    $stack.AddChild($space)

    $btn = New-Object System.Windows.Controls.Button
    $btn.Content = $opt1

    $btn.Width = 65
    $btn.HorizontalAlignment = "center"
    $btn.VerticalAlignment = "bottom"

    #add an event handler
    $btn.Add_click( {
            $script:myInput = $opt1
            $form.Close()
        })

    $stack.AddChild($btn)
    #endregion

    #region BUTTON2
    $space2 = new-object System.Windows.Controls.Label
    $space2.Height = 10
    $stack.AddChild($space2)
    
    $btn2 = New-Object System.Windows.Controls.Button
    $btn2.Content = $opt2

    $btn2.Width = 65
    $btn2.HorizontalAlignment = "center"
    $btn2.VerticalAlignment = "bottom"

    #add an event handler
    $btn2.Add_click( {
            $script:myInput = $opt2
            $form.Close()
        })

    $stack.AddChild($btn2)
    #endregion
    
    #region BUTTON3
    if ($notEnabled)
    {
        $space3 = new-object System.Windows.Controls.Label
        $space3.Height = 10
        $stack.AddChild($space3)
    
        $btn3 = New-Object System.Windows.Controls.Button
        $btn3.Content = $opt3

        $btn3.Width = 65
        $btn3.HorizontalAlignment = "center"
        $btn3.VerticalAlignment = "bottom"

        #add an event handler
        $btn3.Add_click( {
                if (-not $notEnabled) {
                    $script:myInput = $opt3
                }
                $form.Close()
            })

        $stack.AddChild($btn3)
    }
    #endregion

    #add the stack to the form
    $form.AddChild($stack)

    #show the form
    #$inputbox.Focus() | Out-Null
    $form.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen

    $form.ShowDialog() | out-null

    #write the result from the input box back to the pipeline
    $script:myInput
}


Function _Check-MsolSession
{
    Get-MsolDomain
    return $(if ($?) { $true } else { $false })
}

Function Update-MFA
{
    $user = Invoke-InputBox

    if ($user -eq $null)
    {
        Write-Verbose "User cancelled"
        return
    }

    if (-not (_Check-MsolSession))
    {
        Connect-MsolService
    }

    $ms_user = Get-MsolUser -UserPrincipalName $user
    $name = $ms_user.DisplayName

    $update = Invoke-SelectionBox $ms_user
    Write-Verbose "Update: $update"

    if ($update)
    {
        Write-Verbose ("Setting MFA to {0} for {1}" -f $update,$name)
        if ($update -ne "Disabled")
        {
            $auth = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement
            $auth.RelyingParty = "*"
            $auth.State = $update
        }
        else
        {
            $auth = @()
        }
        #$auth.RememberDevicesNotIssuedBefore = (Get-Date)
        Set-MsolUser -UserPrincipalName $user -StrongAuthenticationRequirements $auth
    }
}

Update-MFA