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 |