AzureADAuthenticationMethods.psm1

<#
.SYNOPSIS
    Manage Azure AD users' authentication methods.
.DESCRIPTION
    This module helps Azure AD administrators managing authentication methods for users.
    Get the latest version and report issues here: https://github.com/andres-canello/AzureADAuthMethods
    Andres Canello https://twitter.com/andrescanello
    Version 0.92 - 28 April 2020
.EXAMPLE
    PS C:\>Get-AzureADUserAuthenticationMethod user@contoso.com
    Gets all the authentication methods set for the user.
.EXAMPLE
    PS C:\>Get-AzureADUserAuthenticationMethod -ObjectId user@contoso.com -Phone
    Gets the phone authentication methods set for the user.
.EXAMPLE
    PS C:\>Get-AzureADUserAuthenticationMethod -UserPrincipalName user@contoso.com -Phone
    Gets the phone authentication methods set for the user.
.EXAMPLE
    PS C:\>Get-AzureADUser -SearchString user1@contoso.com | Get-AzureADUserAuthenticationMethod
    Gets the phone authentication methods set for the user from the pipeline.
.EXAMPLE
    PS C:\>New-AzureADUserAuthenticationMethod user@contoso.com -Phone -PhoneNumber '+61412345678' -PhoneType mobile
    Adds a new mobile phone authentication method to the user.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod user@contoso.com -Phone -PhoneNumber '+61412345679' -PhoneType mobile
    Modifies the existing mobile phone number for the user.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod -Phone -UserPrincipalName user1@contoso.com -EnableSmsSignIn
    Enables SMS sign-in for the existing mobile phone authentication method for the user.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod user@contoso.com -Password -NewPassword "password"
    Sets "password" as a new password for the user. Doesn't return the operation result.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod user@contoso.com -Password -NewPassword "password" -ReturnResult
    Sets "password" as a new password for the user and waits 5 seconds for the operation result.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod clouduser@contoso.com -Password
    Sets new system generated password for the user. Not available for syncronised users.
.EXAMPLE
    PS C:\>Remove-AzureADUserAuthenticationMethod -Phone -PhoneType mobile user@contoso.com
    Removes the mobile phone authentication method for the user.
         
.NOTES
    THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR
    FITNESS FOR A PARTICULAR PURPOSE.
    This sample is not supported under any Microsoft standard support program or service.
    The script is provided AS IS without warranty of any kind. Microsoft further disclaims all
    implied warranties including, without limitation, any implied warranties of merchantability
    or of fitness for a particular purpose. The entire risk arising out of the use or performance
    of the sample and documentation remains with you. In no event shall Microsoft, its authors,
    or anyone else involved in the creation, production, or delivery of the script be liable for
    any damages whatsoever (including, without limitation, damages for loss of business profits,
    business interruption, loss of business information, or other pecuniary loss) arising out of
    the use of or inability to use the sample or documentation, even if Microsoft has been advised
    of the possibility of such damages, rising out of the use of or inability to use the sample script,
    even if Microsoft has been advised of the possibility of such damages.
#>




# Update this info
$tenantDomain = '' # REQUIRED -> Change to your tenant domain (contoso.onmicrosoft.com)
$clientId = '' # REQUIRED -> Change to your AppID / ClientId
#$certThumbprint = '1C821E0590DB1E5112323FABF451097731168F8EB' # NOT SUPPORTED YET | OPTIONAL -> Set only if using App Permissions and a certificate to authenticate

# =====================================================================================================================================

$baseURI = 'https://graph.microsoft.com/beta/users/'
$authMethodUri = "$baseUri{0}/authentication/{1}Methods"
$script:authResult = $null
$script:authHeaders = $null


function New-Auth {

    param($aR)

    # If App Permissions, try to get the cert from the cert store
    if ($certThumbprint) {

        $clientCertificate = Get-Item Cert:\CurrentUser\My\$certThumbprint -ErrorAction SilentlyContinue

        if ($clientCertificate) {
            Write-Host "Certificate selected: " $clientCertificate.Subject
            $aR = Get-MsalToken -ClientCertificate $ClientCertificate -ClientId $clientId -TenantId $tenantDomain
        } else {
            Write-Host "Couldn't find a certificate in the local certificate store that matches the configured thumbprint ($certThumbprint)" -ForegroundColor Red
            throw
        }
    } else {
        # if we've done interactive auth, try silently getting a new token
        if ($aR) {

            $user = $aR.Account.Username
            $aR = $null
            $aR = Get-MsalToken -TenantId $tenantDomain -ClientId $clientId -RedirectUri 'urn:ietf:wg:oauth:2.0:oob' -LoginHint $user -Silent

        } else {

            # Interactive auth required
            $aR = Get-MsalToken -TenantId $tenantDomain -ClientId $clientId -RedirectUri 'urn:ietf:wg:oauth:2.0:oob' -Interactive

        }
    }

    return $aR
}

function New-AuthHeaders{

    $aH = $null
    $aH = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]'
    $aH.Add('Authorization', 'Bearer ' + $authResult.AccessToken)
    $aH.Add('Content-Type','application/json')
    $aH.Add('Accept','application/json, text/plain')

    return $aH

}


function Test-TokenValidity {

    if ($authResult) {
        # We have an auth context
        if ($authResult.ExpiresOn.LocalDateTime -gt (Get-Date)) {

            # Token is still valid, nothing to do here.
            $remaining = $authResult.ExpiresOn.LocalDateTime - (Get-Date)
            Write-Host "Access Token valid for $remaining" -ForegroundColor Green

        } else {
            # Token expired, try to get a new one silently from the token cache
            Write-Host 'Access Token expired, getting new token silently' -ForegroundColor Green
            $script:authResult = New-Auth $authResult
            $script:authHeaders = New-AuthHeaders

        }

    } else {
        # No auth context, go interactive
        Write-Host "We need to authenticate first, select a user with the appropriate permissions" -ForegroundColor Green
        $script:authResult = New-Auth
        $script:authHeaders = New-AuthHeaders
    }

}

<#
.SYNOPSIS
    Gets a user's authentication methods.
.DESCRIPTION
    Gets a user's authentication methods.
    All methods are returned by default. Pass the required method as a switch to only get that method.
.EXAMPLE
    PS C:\>Get-AzureADUserAuthenticationMethod -ObjectId user@contoso.com -Phone
    Gets the phone authentication methods set for the user.
.EXAMPLE
    PS C:\>Get-AzureADUser -SearchString user1@contoso.com | Get-AzureADUserAuthenticationMethod
    Gets the phone authentication methods set for the user from the pipeline.
.EXAMPLE
    PS C:\>Get-AzureADUserAuthenticationMethod -UserPrincipalName user@contoso.com -Phone
    Gets the phone authentication methods set for the user.
#>

function Get-AzureADUserAuthenticationMethod {

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $True,ParameterSetName = 'pin')]
        [switch]$Pin,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [switch]$Oath,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [switch]$Phone,

        [Parameter(Mandatory = $True,ParameterSetName = 'email')]
        [switch]$Email,

        [Parameter(Mandatory = $True,ParameterSetName = 'password')]
        [switch]$Password,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [switch]$SecurityQuestion,

        [Parameter(Mandatory = $True,ParameterSetName = 'default')]
        [switch]$Default,

        [Alias('UserId','UPN','UserPrincipalName')]
        [Parameter(Mandatory = $True,ParameterSetName = 'pin',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'oath',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'phone',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'email',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'password',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'default',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'allMethods',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [string]$ObjectId
    )

    Test-TokenValidity

    switch -Wildcard ($PSCmdlet.ParameterSetName) {
        "pin" {
            Write-Host "Getting pin method is not yet supported."
            break
        }
        "oath" {
            Write-Host "Getting oath method is not yet supported."
            break
        }
        "phone" {
            $uri = $authMethodUri -f $ObjectId,'phone'
            $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Get
            $values = ConvertFrom-Json $response.Content

            if ($values.value.count -eq 0) {
                Write-Host "User $ObjectId has no phone auth methods."
                return $null
            } else { return $values.value }

            break
        }
        "email" {
            Write-Host "Getting email method is not yet supported."
            break
        }
        "password" {
            $uri = $authMethodUri -f $ObjectId,'password'
            $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Get
            $values = ConvertFrom-Json $response.Content

            if ($values.value.count -eq 0) {
                Write-Host "User $ObjectId has no password auth methods."
                return $null
            } else { return $values.value }

            break
        }
        "securityQuestion" {
            Write-Host "Getting security question method is not yet supported."
            break
        }
        "default" {
            Write-Host "Getting the default method is not yet supported."
            break
        }
        "allMethods" {
            $uri = $authMethodUri -f $ObjectId,''
            $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Get
            $values = ConvertFrom-Json $response.Content

            if ($values.value.count -eq 0) {
                Write-Host "User $ObjectId has no auth methods."
                return $null
            } else { return $values.value }

            break
        }
    }
}

<#
.SYNOPSIS
    Creates a new authentication method for the user.
.DESCRIPTION
    Creates a new authentication method for the user.
    Use to create a new method type for the user. To modify a method, use Set-AzureADUserAuthenticationMethod.
.EXAMPLE
    PS C:\>New-AzureADUserAuthenticationMethod user@contoso.com -Phone -PhoneNumber '+61412345678' -PhoneType mobile
    Adds a new mobile phone authentication method to the user.
#>

function New-AzureADUserAuthenticationMethod {

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $True,ParameterSetName = 'pin')]
        [switch]$Pin,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [switch]$Oath,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [switch]$Phone,

        [Parameter(Mandatory = $True,ParameterSetName = 'email')]
        [switch]$Email,

        [Parameter(Mandatory = $True,ParameterSetName = 'password')]
        [switch]$Password,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [switch]$SecurityQuestion,

        [Parameter(Mandatory = $True,ParameterSetName = 'default')]
        [switch]$Default,

        [Alias('UserId','UPN','UserPrincipalName')]
        [Parameter(Mandatory = $True,ParameterSetName = 'pin',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'oath',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'phone',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'email',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'password',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'default',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [string]$ObjectId,

        [Parameter(Mandatory = $True,ParameterSetName = 'pin',Position = 2)]
        [string]$NewPin,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$SecretKey,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [int]$TimeIntervalInSeconds,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$SerialNumber,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$Manufacturer,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$Model,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [string]$PhoneNumber,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [ValidateSet("mobile","alternateMobile","office")] [string]$PhoneType,

        [Parameter(Mandatory = $True,ParameterSetName = 'email',Position = 2)]
        [string]$EmailAddress,

        [Parameter(Mandatory = $True,ParameterSetName = 'password')]
        [string]$NewPassword,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [string]$Question,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [string]$Answer

    )

    switch -Wildcard ($PSCmdlet.ParameterSetName) {
        "pin" {
            Write-Host "Setting pin method is not yet supported."
            break
        }
        "oath" {
            Write-Host "Setting oath method is not yet supported."
            break
        }
        "phone" {
            Test-TokenValidity
            $uri = $authMethodUri -f $ObjectId,'phone'
            $postParams = @{}
            $postParams.phoneNumber = $phoneNumber
            $postParams.phoneType = $phoneType

            $json = $postparams | ConvertTo-Json -Depth 99 -Compress

            $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Post -Body $json
            $values = ConvertFrom-Json $response.Content

            return $values
            break
        }
        "email" {
            Write-Host "Setting email method is not yet supported."
            break
        }
        "password" {
            Write-Host "Setting password method is not yet supported."
            break
        }
        "securityQuestion" {
            Write-Host "Setting security question method is not yet supported."
            break
        }

    }

}

<#
.SYNOPSIS
    Modifies an authentication method for the user. Manages SMS Sign In for mobile phone method.
.DESCRIPTION
    Modifies an authentication method for the user. Manages SMS Sign In for mobile phone method.
    Use to modify an existing authentication method for the user. To create a new method, use New-AzureADUserAuthenticationMethod.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod user@contoso.com -Phone -PhoneNumber '+61412345679' -PhoneType mobile
    Modifies the existing mobile phone number for the user.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod -Phone -UPN user1@contoso.com -EnableSmsSignIn
    Enables SMS sign-in for the existing mobile phone authentication method for the user.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod user@contoso.com -Password -NewPassword "password"
    Sets "password" as a new password for the user. Doesn't return the operation result.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod user@contoso.com -Password -NewPassword "password" -ReturnResult
    Sets "password" as a new password for the user and waits 5 seconds for the operation result.
.EXAMPLE
    PS C:\>Set-AzureADUserAuthenticationMethod clouduser@contoso.com -Password
    Sets new system generated password for the user. Not available for syncronised users.
#>

function Set-AzureADUserAuthenticationMethod {

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $True,ParameterSetName = 'pin')]
        [switch]$Pin,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [switch]$Oath,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [Parameter(Mandatory = $True,ParameterSetName = 'enableSmsSignIn')]
        [Parameter(Mandatory = $True,ParameterSetName = 'disableSmsSignIn')]
        [switch]$Phone,

        [Parameter(Mandatory = $True,ParameterSetName = 'email')]
        [switch]$Email,

        [Parameter(Mandatory = $True,ParameterSetName = 'password')]
        [switch]$Password,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [switch]$SecurityQuestion,

        [Parameter(Mandatory = $True,ParameterSetName = 'default')]
        [switch]$Default,

        [Alias('UserId','UPN','UserPrincipalName')]
        [Parameter(Mandatory = $True,ParameterSetName = 'pin',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'oath',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'phone',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'email',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'password',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'default',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'enableSmsSignIn',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'disableSmsSignIn',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [string]$ObjectId,

        [Parameter(Mandatory = $True,ParameterSetName = 'pin',Position = 2)]
        [string]$NewPin,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$SecretKey,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [int]$TimeIntervalInSeconds,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$SerialNumber,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$Manufacturer,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$Model,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [string]$PhoneNumber,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [Parameter(Mandatory = $False,ParameterSetName = 'default')]
        [ValidateSet("mobile","alternateMobile","office")] [string]$PhoneType,

        [Parameter(Mandatory = $True,ParameterSetName = 'email',Position = 2)]
        [string]$EmailAddress,

        [Parameter(Mandatory = $False,ParameterSetName = 'password')]
        [string]$NewPassword,

        [Parameter(Mandatory = $False,ParameterSetName = 'password')]
        [switch]$ReturnResult,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [string]$Question,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [string]$Answer,

        [Parameter(Mandatory = $True,ParameterSetName = 'default')]
        [string]$DefaultMethod,

        [Parameter(Mandatory = $True,ParameterSetName = 'enableSmsSignIn')]
        [switch]$EnableSmsSignIn,

        [Parameter(Mandatory = $True,ParameterSetName = 'disableSmsSignIn')]
        [switch]$DisableSmsSignIn

    )

    Test-TokenValidity

    switch -Wildcard ($PSCmdlet.ParameterSetName) {
        "pin" {
            Write-Host "Setting pin method is not yet supported."
            break
        }
        "oath" {
            Write-Host "Setting oath method is not yet supported."
            break
        }
        "phone" {
            if ($phoneType -eq "alternateMobile") { $methodId = "b6332ec1-7057-4abe-9331-3d72feddfe41" }
            elseif ($phoneType -eq "mobile") { $methodId = "3179e48a-750b-4051-897c-87b9720928f7" }
            else { $methodId = "e37fc753-ff3b-4958-9484-eaa9425c82bc" }

            $uri = $authMethodUri -f $ObjectId,'phone' + "/$methodId"
            $postParams = @{}
            $postParams.phoneNumber = $phoneNumber
            $postParams.phoneType = $phoneType

            $json = $postparams | ConvertTo-Json -Depth 99 -Compress

            $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Put -Body $json
            $values = ConvertFrom-Json $response.Content

            return $values
            break
        }
        "email" {
            Write-Host "Setting email method is not yet supported."
            break
        }
        "password" {
            $uri = $authMethodUri -f $ObjectId,'password' + "/28c10230-6103-485e-b985-444c60001490/resetPassword"
            if ($newPassword){
                $postParams = @{}
                $postParams.newPassword = $newPassword
                $json = $postparams | ConvertTo-Json -Depth 99 -Compress
    
                $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Post -Body $json
            }else{
                $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Post
            }
            $values = ConvertFrom-Json $response.Content

            # Check password reset result
            if (($response.StatusCode -eq "202") -and $returnResult){
                Write-Host "Waiting for a response..."
                Start-Sleep -Seconds 5
                $oR = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $response.Headers.Location -Method Get
                $operationResult = ConvertFrom-Json $oR.Content

                $operationResult
            }
            
            return $values    
            break
        }
        "securityQuestion" {
            Write-Host "Setting security question method is not yet supported."
            break
        }
        "default" {
            Write-Host "Setting the default method is not yet supported."
            break
        }
        "enableSmsSignIn" {
            $uri = $authMethodUri -f $ObjectId,'phone' + "/3179e48a-750b-4051-897c-87b9720928f7/enableSmsSignIn"
            $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Post
            $values = ConvertFrom-Json $response.Content

            return $values
            break
        }
        "disableSmsSignIn" {
            $uri = $authMethodUri -f $ObjectId,'phone' + "/3179e48a-750b-4051-897c-87b9720928f7/disableSmsSignIn"
            $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Post
            $values = ConvertFrom-Json $response.Content

            return $values
            break
        }
    }


}

<#
.SYNOPSIS
    Removes an authentication method from the user.
.DESCRIPTION
    Removes an authentication method from the user.
    Use to remove an existing authentication method for the user.
.EXAMPLE
    PS C:\>Remove-AzureADUserAuthenticationMethod -Phone -PhoneType mobile user@contoso.com
    Removes the mobile phone authentication method for the user.
#>

function Remove-AzureADUserAuthenticationMethod {

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $True,ParameterSetName = 'pin')]
        [switch]$Pin,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [switch]$Oath,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [switch]$Phone,

        [Parameter(Mandatory = $True,ParameterSetName = 'email')]
        [switch]$Email,

        [Parameter(Mandatory = $True,ParameterSetName = 'password')]
        [switch]$Password,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [switch]$SecurityQuestion,

        [Alias('UserId','UPN','UserPrincipalName')]
        [Parameter(Mandatory = $True,ParameterSetName = 'pin',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'oath',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'phone',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'email',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'password',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Parameter(Mandatory = $True,ParameterSetName = 'default',Position = 1,ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [string]$ObjectId,

        [Parameter(Mandatory = $True,ParameterSetName = 'oath')]
        [string]$SerialNumber,

        [Parameter(Mandatory = $True,ParameterSetName = 'phone')]
        [ValidateSet("mobile","alternateMobile","office")] [string]$PhoneType,

        [Parameter(Mandatory = $True,ParameterSetName = 'email',Position = 2)]
        [string]$EmailAddress,

        [Parameter(Mandatory = $True,ParameterSetName = 'securityQuestion')]
        [string]$Question

    )

    switch -Wildcard ($PSCmdlet.ParameterSetName) {
        "pin" {
            Write-Host "Removing pin method is not yet supported."
            break
        }
        "oath" {
            Write-Host "Removing oath method is not yet supported."
            break
        }
        "phone" {
            Test-TokenValidity
            if ($phoneType -eq "alternateMobile") { $methodId = "b6332ec1-7057-4abe-9331-3d72feddfe41" }
            elseif ($phoneType -eq "mobile") { $methodId = "3179e48a-750b-4051-897c-87b9720928f7" }
            else { $methodId = "e37fc753-ff3b-4958-9484-eaa9425c82bc" }


            $uri = $authMethodUri -f $ObjectId,'phone' + "/$methodId"
            $response = Invoke-WebRequest -UseBasicParsing -Headers $authHeaders -Uri $uri -Method Delete
            $values = ConvertFrom-Json $response.Content

            return $values
            break
        }
        "email" {
            Write-Host "Deleting email method is not yet supported."
            break
        }
        "securityQuestion" {
            Write-Host "Setting security question method is not yet supported."
            break
        }

    }
}

# Run this when the module is loaded
$MSAL = Get-Module -ListAvailable MSAL.ps -Verbose:$false -ErrorAction SilentlyContinue
if (-not $MSAL) {

    Write-Host "Please install the MSAL.ps PowerShell module (Install-Module MSAL.ps) and try again" -ForegroundColor Red
    throw
}

if (($tenantDomain -eq '') -or ($clientId -eq '')) {

    Write-Host "Please open the file AzureADAuthenticationMethods.psm1 and update with your tenant domain and Client Id" -ForegroundColor Red 
    throw
}

Export-ModuleMember -Function Get-AzureADUserAuthenticationMethod
Export-ModuleMember -Function New-AzureADUserAuthenticationMethod
Export-ModuleMember -Function Set-AzureADUserAuthenticationMethod
Export-ModuleMember -Function Remove-AzureADUserAuthenticationMethod

# SIG # Begin signature block
# MIIjgwYJKoZIhvcNAQcCoIIjdDCCI3ACAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAVtNoHu0a010p5
# ioexGIfV35nGatyxohhTMnH7KXbjqqCCDYEwggX/MIID56ADAgECAhMzAAABh3IX
# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB
# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH
# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d
# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ
# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV
# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy
# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K
# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV
# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr
# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx
# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe
# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g
# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf
# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI
# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5
# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea
# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVWDCCFVQCAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgOX8XdIMR
# +e9hO7IOJZxG8HopQCvpesqNMcB+yYAD7pAwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
# BgkqhkiG9w0BAQEFAASCAQBSEpcoLKsPTgTFCrNzSg+yNZoWLf1x+ODuszOOp7ai
# qMnLrW9XEPfsDgcW5TUaqs0qkVczQ/vTUXACIsk8tyiKvgGiwwk76ih0td7400q3
# DpzVwWUCVOJHcFYeEVTritgJhxFIaCB+Ltnrx+eccEhzIsGa+mdqFffFSFJ+GgXV
# DLTh8FHuxBR2T6Ox6z/ggrq07td5c//z82F24hfl3y3wkooEFIeQVt96RTooxVlm
# 3XKvnUqopgrhzpjmd1nQvXozN4l39jjmfMXVBZpb/ngWMHr/gVzjJG5Zyax6dUzp
# GZvXNLkyDZ02F021Dj1HaLHEXjIXn0J8KfUMGnEsIU7soYIS4jCCEt4GCisGAQQB
# gjcDAwExghLOMIISygYJKoZIhvcNAQcCoIISuzCCErcCAQMxDzANBglghkgBZQME
# AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEIJlNk0Ez7ht+uqZq3g208zfm0M1ao3ofs00Vz1VI
# lxhCAgZfOtKtBg8YEzIwMjAwOTA3MDUyMzQ4LjA3NFowBIACAfSggdCkgc0wgcox
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p
# Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg
# RVNOOjhBODItRTM0Ri05RERBMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt
# cCBTZXJ2aWNloIIOOTCCBPEwggPZoAMCAQICEzMAAAEZjLtUCApd/mUAAAAAARkw
# DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN
# MTkxMTEzMjE0MDM2WhcNMjEwMjExMjE0MDM2WjCByjELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg
# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046OEE4Mi1FMzRGLTlE
# REExJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0G
# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCMZ+Y4IJyscExdMO2Lyc1ZLSGhtDyg
# A31Gy5Pd7OGmffKmO5CFgrb1vGDOdVktl2lNqZO7tV+jQ2Epg7B4CplAd02H1xz3
# R0C2MnE4Jz9hqi0+4b3+NAD5rgAUmUc6gbVdCNQBDZX81gCdmHqqeIPCn7bDyVpF
# A2Pri+zQOxGzkpF70kUbLZjJy9uv634FgRZ9OfDYqMhR9O5BfU701dcuKg2pt/Cr
# V9wXHukAsPzIDEyjRyCXnnOIt6+nMvB6FKkVBnaSwsNVorwTadqw7cBC4u8TY4kz
# 5BJMq60a0wjuikQ68MCuzzU2CqqB/nciA4AvUro9XFwl3dMkn8pO1WOLAgMBAAGj
# ggEbMIIBFzAdBgNVHQ4EFgQU0xiHCX5C9j+NFxa+pPcZsLTFSuEwHwYDVR0jBBgw
# FoAU1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov
# L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENB
# XzIwMTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAx
# MC0wNy0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDAN
# BgkqhkiG9w0BAQsFAAOCAQEAgIuJP8i1dROlPfSPcnjESfDMEprKwtiTV/TlDMEw
# cc+Fn2tJOeyqZ4IDeuKJ0SMweUuJNxnqYUiTv7WkYy4Q6YvKzFnesd4nbJCWk2ZQ
# lO0nGAnaZPtiJYCmf4B/hGn29Ei+X/5QUw18axU6rWJKbd+kzpUMDdL+XnV7Bhgj
# MxYIxrbTrUHAylo8rJ8nluqVh0L9WenvIgYK+6ReVQf3v+XgIy5UyiaMHfK+j+GX
# rmM9RhaEbIWaDu7nI3q9KVSWCWq+fqpS2yof0ba0Vc065IPelejxsTBak+wI8vOF
# 0zz+FYlnHuc+GvHGszeBjXmsRP1W/E3TEG3cfUD7S4goSDCCBnEwggRZoAMCAQIC
# CmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRp
# ZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIxMzY1NVoXDTI1MDcwMTIx
# NDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG
# A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggEiMA0GCSqGSIb3
# DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX9fp/aZRrdFQQ1aUKAIKF
# ++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkTjnxhMFmxMEQP8WCIhFRD
# DNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG8lhHhjKEHnRhZ5FfgVSx
# z5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGKr0tkiVBisV39dx898Fd1
# rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6Kgox8NpOBpG2iAg16Hgc
# sOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEFTyJNAgMBAAGjggHmMIIB
# 4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6XIoxkPNDe3xGG8UzaFqF
# bVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
# EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYD
# VR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwv
# cHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEB
# BE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9j
# ZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwgaAGA1UdIAEB/wSBlTCB
# kjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFodHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRtMEAGCCsGAQUFBwICMDQe
# MiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0AGEAdABlAG0AZQBuAHQA
# LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/gXEDPZ2joSFvs+umzPUx
# vs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtUVwgrUYJEEvu5U4zM9GAS
# inbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9Wj8c8pl5SpFSAK84Dxf1
# L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9BOFwnzJKJ/1Vry/+tuWO
# M7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOdeyFtw5yjojz6f32WapB4
# pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1JeVk7Pf0v35jWSUPei45
# V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4TtxCd9ddJgiCGHasFAeb73x
# 4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5u+zGy9iCtHLNHfS4hQEe
# gPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9UJyH3yKxO2ii4sanblrKn
# QqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Zta7cRDyXUHHXodLFVeNp
# 3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa7wknHNWzfjUeCLraNtvT
# X4/edIhJEqGCAsswggI0AgEBMIH4oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP
# cGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo4QTgyLUUzNEYtOURE
# QTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcG
# BSsOAwIaAxUAh1b9Y65IOBNFKzLT9G6vsJuJNLaggYMwgYCkfjB8MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg
# VGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOL/rokwIhgPMjAy
# MDA5MDcwMjUyNTdaGA8yMDIwMDkwODAyNTI1N1owdDA6BgorBgEEAYRZCgQBMSww
# KjAKAgUA4v+uiQIBADAHAgEAAgIJezAHAgEAAgIRujAKAgUA4wEACQIBADA2Bgor
# BgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAID
# AYagMA0GCSqGSIb3DQEBBQUAA4GBAIkXkvZjtSxNgh5ZxgrdB5ABPOtDRFGEkSRb
# zOhQ9KFsF2XLutiLvIaKJgilYdEASyRzOZ7YuwX+C2ShRJYRpoLtBZhO/aUpmwRi
# czFycv8iomdpsFxe3HCUSTk494VqlhJ9GRFvQyoNoKpRxy7sEdsRnjPAW8KPVFx/
# yOZTmrF4MYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
# MTACEzMAAAEZjLtUCApd/mUAAAAAARkwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqG
# SIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgtvR53w36aisT
# 8sgKhq+oR5XqhIuQHHk+x92AbFrktWMwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHk
# MIG9BCCrvh3sU+umYe5PxTcM1ZyUFxjf/JnEZoCF//9l8GjVRDCBmDCBgKR+MHwx
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABGYy7VAgKXf5lAAAAAAEZ
# MCIEIGYZEVFeDFNvKwtAqoX/sQRRJbMVYsMtIIqe5PhD9Ok/MA0GCSqGSIb3DQEB
# CwUABIIBAENRV8B3Ed6YZRa8EJL7CzNZ61evKGvZvFTrBhygBdqS9YC6eVst2PKy
# nQACR+sJbUP1zKz31uOmI2sDpLr5jp3SATtNDMikTGZKqqwdT4nFxPE0MreLwYMU
# KnI90e9WYX938X3IE+fQcFP3hJ1R43W+iX0LP4mg/QARgeMzjK2D4NstoaEGQQ57
# HUuB0/OiMRvdl23ZTbky9EEsNswoVVKGREfC/eVNV2PGAFtjR91I9fhAUzpSM8hs
# 4nZS94+GprwyGfwDhJOsbO4fNCnZz/vxaZL5ax7tc4XYDm62dt5alIOrSSSfYkAZ
# IckFbGZoy4EbvmueXCeJwQnNhJQHUfg=
# SIG # End signature block