AzureADAuthMethods.psm1
$script:ModuleRoot = $PSScriptRoot $script:ModuleVersion = (Import-PowerShellDataFile -Path "$($script:ModuleRoot)\AzureADAuthMethods.psd1").ModuleVersion # Detect whether at some level dotsourcing was enforced $script:doDotSource = $false if ($AzureADAuthMethods_dotsourcemodule) { $script:doDotSource = $true } <# Note on Resolve-Path: All paths are sent through Resolve-Path/Resolve-PSFPath in order to convert them to the correct path separator. This allows ignoring path separators throughout the import sequence, which could otherwise cause trouble depending on OS. Resolve-Path can only be used for paths that already exist, Resolve-PSFPath can accept that the last leaf my not exist. This is important when testing for paths. #> # Detect whether at some level loading individual module files, rather than the compiled module was enforced $importIndividualFiles = $false if ($AzureADAuthMethods_importIndividualFiles) { $importIndividualFiles = $true } if (Test-Path "$($script:ModuleRoot)\..\.git") { $importIndividualFiles = $true } if ("<was compiled>" -eq '<was not compiled>') { $importIndividualFiles = $true } function Import-ModuleFile { <# .SYNOPSIS Loads files into the module on module import. .DESCRIPTION This helper function is used during module initialization. It should always be dotsourced itself, in order to proper function. This provides a central location to react to files being imported, if later desired .PARAMETER Path The path to the file to load .EXAMPLE PS C:\> . Import-ModuleFile -File $function.FullName Imports the file stored in $function according to import policy #> [CmdletBinding()] Param ( [string] $Path ) $resolvedPath = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($Path).ProviderPath if ($doDotSource) { . $resolvedPath } else { $ExecutionContext.InvokeCommand.InvokeScript($false, ([scriptblock]::Create([io.file]::ReadAllText($resolvedPath))), $null, $null) } } #region Load individual files if ($importIndividualFiles) { # Execute Preimport actions foreach ($path in (& "$ModuleRoot\internal\scripts\preimport.ps1")) { . Import-ModuleFile -Path $path } # Import all internal functions foreach ($function in (Get-ChildItem "$ModuleRoot\internal\functions" -Filter "*.ps1" -Recurse -ErrorAction Ignore)) { . Import-ModuleFile -Path $function.FullName } # Import all public functions foreach ($function in (Get-ChildItem "$ModuleRoot\functions" -Filter "*.ps1" -Recurse -ErrorAction Ignore)) { . Import-ModuleFile -Path $function.FullName } # Execute Postimport actions foreach ($path in (& "$ModuleRoot\internal\scripts\postimport.ps1")) { . Import-ModuleFile -Path $path } # End it here, do not load compiled code below return } #endregion Load individual files #region Load compiled code function Assert-GraphConnection { <# .SYNOPSIS Asserts a valid graph connection has been established. .DESCRIPTION Asserts a valid graph connection has been established. .PARAMETER Cmdlet The $PSCmdlet variable of the calling command. .EXAMPLE PS C:\> Assert-GraphConnection -Cmdlet $PSCmdlet Asserts a valid graph connection has been established. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Cmdlet ) process { if ($script:msgraphToken) { return } $exception = [System.InvalidOperationException]::new('Not yet connected to MSGraph. Use Connect-AzureADUserAuthenticationMethod to establish a connection!') $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception, "NotConnected", 'InvalidOperation', $null) $Cmdlet.ThrowTerminatingError($errorRecord) } } function ConvertTo-AuthHeader { <# .SYNOPSIS Generates an authentication header from a graph token. .DESCRIPTION Generates an authentication header from a graph token. .PARAMETER Token The token from which to build the authentication header. .EXAMPLE PS C:\> Get-Token | ConvertTo-AuthHeader Generates an authentication header from a graph token. #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] $Token ) process { foreach ($tokenObject in $Token) { @{ Authorization = "Bearer $($tokenObject.AccessToken)" 'Content-Type' = 'application/json' 'Accept' = 'application/json, text/plain' } } } } function Get-Token { <# .SYNOPSIS Returns the token to use for authentication to MSGraph. .DESCRIPTION Returns the token to use for authentication to MSGraph. Automatically refreshes it if it is close to expiration. .EXAMPLE PS C:\> Get-Token Returns the token to use for authentication to MSGraph. #> [CmdletBinding()] Param ( ) process { if ($script:msgraphToken -and $script:msgraphToken.ExpiresOn.LocalDateTime -gt (Get-Date).AddMinutes(3)) { return $script:msgraphToken } $parameters = @{ TenantId = $script:tenantID ClientId = $script:clientID ErrorAction = 'Stop' } if ($script:clientCertificate) { $parameters.ClientCertificate = $script:clientCertificate } else { $parameters.RedirectUri = $script:redirectUri $parameters.LoginHint = $script:msgraphToken.Account.Username $parameters.Silent = $true } try { $token = Get-MsalToken @parameters } catch { Write-Warning "Failed to re-authenticate to tenant $script:tenantID : $_" throw } $script:msgraphToken = $token return $token } } function Invoke-AzureAdRequest { <# .SYNOPSIS Execute an arbitrary graph call against AzureAD endpoints. .DESCRIPTION Execute an arbitrary graph call against AzureAD endpoints. Handles authentication & token refresh transparently. .PARAMETER Query The actual query to execute. .PARAMETER Method The REST method to apply .PARAMETER Body Any body data to pass along as part of the request .PARAMETER GetValues Get the content of the .Value property, rather than the raw response content .PARAMETER Raw Get raw response .EXAMPLE PS C:\> Invoke-AzureAdRequest -Query 'users/3ec9f2ec-aeec-4ad9-ad18-b456288fdb32/authentication/phonemethods' -Method GET Retrieve the phone authentication settings for the specified user. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $Query, [Parameter(Mandatory = $true)] [string] $Method, $Body, [switch] $GetValues, [switch] $Raw ) begin { try { $authHeader = Get-Token | ConvertTo-AuthHeader } catch { throw } $parameters = @{ Method = $Method Uri = "$($script:baseUri.Trim("/"))/$($Query.TrimStart("/"))" Headers = $authHeader } if ($Body) { $parameters.Body = $Body } } process { try { $response = Invoke-RestMethod @parameters -ErrorAction Stop } catch { throw } if ($Raw) { return $response } if ($GetValues) { return $response.Value } $response.Value } } function Connect-AzureADUserAuthenticationMethod { [CmdletBinding(DefaultParameterSetName = 'Interactive')] param ( [Parameter(Mandatory = $true)] [string] $TenantId, [Parameter(Mandatory = $true, ParameterSetName = 'Certificate')] [System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate, [Parameter(Mandatory = $true, ParameterSetName = 'Thumbprint')] [string] $Thumbprint, [Parameter(ParameterSetName = 'Thumbprint')] [string] $CertificateStore = 'Cert:\CurrentUser\My', [Parameter(ParameterSetName = 'Interactive')] [switch] $Interactive, [Parameter(ParameterSetName = 'Interactive')] [switch] $DeviceCode, [string] $ClientID = "", [string] $RedirectUri = "urn:ietf:wg:oauth:2.0:oob", [string] $BaseUri = 'https://graph.microsoft.com/beta/', [switch] $PassThru ) process { if ($Thumbprint) { try { $Certificate = Get-Item -Path (Join-Path -Path $CertificateStore -ChildPath $Thumbprint) } catch { throw "Unable to find certificate $Thumbprint in certificate store $CertificateStore !" } } switch ($PSCmdlet.ParameterSetName) { 'Interactive' { try { $token = Get-MsalToken -TenantId $TenantId -ClientId $ClientID -RedirectUri $RedirectUri -Interactive -DeviceCode:$DeviceCode } catch { Write-Warning "Failed to authenticate to tenant $TenantID : $_" throw } } default { try { $token = Get-MsalToken -TenantId $TenantId -ClientId $ClientID -ClientCertificate $Certificate } catch { Write-Warning "Failed to authenticate to tenant $TenantID : $_" throw } } } $script:msgraphToken = $token $script:baseUri = $BaseUri $script:tenantID = $TenantId $script:clientID = $ClientID $script:redirectUri = $RedirectUri $script:clientCertificate = $Certificate if ($PassThru) { $token } } } function Get-AzureADUserAuthenticationMethod { <# .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. #> [CmdletBinding(DefaultParameterSetName = 'allMethods')] param ( [Parameter(Mandatory = $True, ParameterSetName = 'pin')] [switch] $Pin, [Parameter(Mandatory = $True, ParameterSetName = 'softwareOath')] [switch] $softwareOath, [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 = 'FIDO2')] [switch] $FIDO2, [Parameter(Mandatory = $True, ParameterSetName = 'passwordlessMicrosoftAuthenticator')] [switch] $PasswordlessMicrosoftAuthenticator, [Parameter(Mandatory = $True, ParameterSetName = 'MicrosoftAuthenticator')] [switch] $MicrosoftAuthenticator, [Parameter(Mandatory = $True, ParameterSetName = 'WindowsHelloForBusiness')] [switch] $WindowsHelloForBusiness, [Parameter(Mandatory = $True, ParameterSetName = 'default')] [switch] $Default, [Alias('UserId', 'UPN', 'UserPrincipalName')] [Parameter(Mandatory = $True, Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string] $ObjectId ) begin { Assert-GraphConnection -Cmdlet $PSCmdlet $common = @{ Method = 'GET' GetValues = $false } } process { $values = switch ($PSCmdlet.ParameterSetName) { "phone" { Invoke-AzureAdRequest @common -Query "users/$ObjectId/authentication/phoneMethods" break } "email" { Invoke-AzureAdRequest @common -Query "users/$ObjectId/authentication/emailMethods" break } "password" { Invoke-AzureAdRequest @common -Query "users/$ObjectId/authentication/passwordMethods" break } "FIDO2" { Invoke-AzureAdRequest @common -Query "users/$ObjectId/authentication/fido2Methods" break } "passwordlessMicrosoftAuthenticator" { Invoke-AzureAdRequest @common -Query "users/$ObjectId/authentication/passwordlessMicrosoftAuthenticatorMethods" break } "MicrosoftAuthenticator" { Invoke-AzureAdRequest @common -Query "users/$ObjectId/authentication/MicrosoftAuthenticatorMethods" break } "WindowsHelloForBusiness" { Invoke-AzureAdRequest @common -Query "users/$ObjectId/authentication/windowsHelloForBusinessMethods" break } "allMethods" { Invoke-AzureAdRequest @common -Query "users/$ObjectId/authentication/methods" break } default { throw "Getting the $($PSCmdlet.ParameterSetName) method is not yet supported." } } $values | Add-Member -NotePropertyName userObjectId -NotePropertyValue $ObjectId -PassThru } } function New-AzureADUserAuthenticationMethod { <# .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 Update-AzureADUserAuthenticationMethod. .EXAMPLE PS C:\>New-AzureADUserAuthenticationMethod user@contoso.com -Phone -PhoneNumber '+61412345678' -PhoneType mobile Adds a new mobile phone authentication method to the user. #> [CmdletBinding()] param ( [Parameter(Mandatory = $True, ParameterSetName = 'pin')] [switch] $Pin, [Parameter(Mandatory = $True, ParameterSetName = 'oath')] [switch] $Oath, [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, 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 ) begin { Assert-GraphConnection -Cmdlet $PSCmdlet } process { switch ($PSCmdlet.ParameterSetName) { "phone" { $postParams = @{ phoneNumber = $PhoneNumber phoneType = $PhoneType } $json = $postparams | ConvertTo-Json -Depth 99 -Compress Invoke-AzureAdRequest -Method POST -Query "users/$ObjectId/authentication/phoneMethods" -Body $json break } "email" { $postParams = @{ emailAddress = $EmailAddress } $json = $postparams | ConvertTo-Json -Depth 99 -Compress Invoke-AzureAdRequest -Method POST -Query "users/$ObjectId/authentication/emailMethods" -Body $json break } default { throw "Setting the $($PSCmdlet.ParameterSetName) method is not yet supported." } } } } function Remove-AzureADUserAuthenticationMethod { <# .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. #> [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 = 'FIDO2')] [switch] $FIDO2, [Parameter(Mandatory = $True, ParameterSetName = 'passwordlessMicrosoftAuthenticator')] [switch] $PasswordlessMicrosoftAuthenticator, [Parameter(Mandatory = $True, ParameterSetName = 'MicrosoftAuthenticator')] [switch] $MicrosoftAuthenticator, [Parameter(Mandatory = $True, ParameterSetName = 'WindowsHelloForBusiness')] [switch] $WindowsHelloForBusiness, [Parameter(Mandatory = $True, ParameterSetName = 'FIDO2')] [Parameter(Mandatory = $True, ParameterSetName = 'passwordlessMicrosoftAuthenticator')] [Parameter(Mandatory = $True, ParameterSetName = 'MicrosoftAuthenticator')] [Parameter(Mandatory = $True, ParameterSetName = 'WindowsHelloForBusiness')] [string] $MethodId, [Parameter(Mandatory = $True, ParameterSetName = 'securityQuestion')] [switch] $SecurityQuestion, [Alias('UserId', 'UPN', 'UserPrincipalName')] [Parameter(Mandatory = $True, 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 = 'securityQuestion')] [string] $Question ) begin { Assert-GraphConnection -Cmdlet $PSCmdlet } process { switch ($PSCmdlet.ParameterSetName) { "phone" { $methodId = switch ($PhoneType) { 'alternateMobile' { 'b6332ec1-7057-4abe-9331-3d72feddfe41' } 'mobile' { '3179e48a-750b-4051-897c-87b9720928f7' } 'office' { 'e37fc753-ff3b-4958-9484-eaa9425c82bc' } } Invoke-AzureAdRequest -Method DELETE -Query "users/$ObjectId/authentication/phoneMethods/$methodId" break } "email" { Invoke-AzureAdRequest -Method DELETE -Query "users/$ObjectId/authentication/emailMethods/3ddfcfc8-9383-446f-83cc-3ab9be4be18f" break } "FIDO2" { Invoke-AzureAdRequest -Method DELETE -Query "users/$ObjectId/authentication/fido2Methods/$MethodId" break } "passwordlessMicrosoftAuthenticator" { Invoke-AzureAdRequest -Method DELETE -Query "users/$ObjectId/authentication/passwordlessMicrosoftAuthenticatorMethods/$MethodId" break } "MicrosoftAuthenticator" { Invoke-AzureAdRequest -Method DELETE -Query "users/$ObjectId/authentication/MicrosoftAuthenticatorMethods/$MethodId" break } "WindowsHelloForBusiness" { Invoke-AzureAdRequest -Method DELETE -Query "users/$ObjectId/authentication/windowsHelloForBusinessMethods/$MethodId" break } default { throw "Removing the $($PSCmdlet.ParameterSetName) method is not yet supported." } } } } function Update-AzureADUserAuthenticationMethod { <# .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:\>Update-AzureADUserAuthenticationMethod user@contoso.com -Phone -PhoneNumber '+61412345679' -PhoneType mobile Modifies the existing mobile phone number for the user. .EXAMPLE PS C:\>Update-AzureADUserAuthenticationMethod -Phone -UPN user1@contoso.com -EnableSmsSignIn Enables SMS sign-in for the existing mobile phone authentication method for the user. .EXAMPLE PS C:\>Update-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:\>Update-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:\>Update-AzureADUserAuthenticationMethod clouduser@contoso.com -Password Sets new system generated password for the user. Not available for syncronised users. #> [CmdletBinding()] param ( [Parameter(Mandatory = $True, ParameterSetName = 'pin')] [switch] $Pin, [Parameter(Mandatory = $True, ParameterSetName = 'oath')] [switch] $Oath, [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, 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 = $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 ) begin { Assert-GraphConnection -Cmdlet $PSCmdlet } process { switch ($PSCmdlet.ParameterSetName) { "phone" { $methodId = switch ($PhoneType) { 'alternateMobile' { 'b6332ec1-7057-4abe-9331-3d72feddfe41' } 'mobile' { '3179e48a-750b-4051-897c-87b9720928f7' } 'office' { 'e37fc753-ff3b-4958-9484-eaa9425c82bc' } } $postParams = @{ phoneNumber = $PhoneNumber phoneType = $PhoneType } $json = $postparams | ConvertTo-Json -Depth 99 -Compress Invoke-AzureAdRequest -Method PUT -Query "users/$ObjectId/authentication/phoneMethods/$methodId" -Body $json break } "email" { $postParams = @{ emailAddress = $EmailAddress } $json = $postparams | ConvertTo-Json -Depth 99 -Compress Invoke-AzureAdRequest -Method PUT -Query "users/$ObjectId/authentication/emailMethods/3ddfcfc8-9383-446f-83cc-3ab9be4be18f" -Body $json break } "password" { $parameters = @{ Method = 'POST' Query = "users/$ObjectId/authentication/passwordMethods/28c10230-6103-485e-b985-444c60001490/resetPassword" } if ($NewPassword) { $parameters.Body = @{ newPassword = $NewPassword } | ConvertTo-Json -Depth 99 -Compress } $response = Invoke-AzureAdRequest @parameters -Raw if (-not $ReturnResult) { return $response } # TODO: If RAW, use invoke-webrequest to get response headers. # Check password reset result if ($response.StatusCode -eq "202") { Write-Host "Waiting for a response..." Start-Sleep -Seconds 5 (Invoke-WebRequest -UseBasicParsing -Headers (Get-Token | ConvertTo-AuthHeader) -Uri $response.Headers.Location -Method Get).Content } return $response.Content } "enableSmsSignIn" { Invoke-AzureAdRequest -Method PUT -Query "users/$ObjectId/authentication/phoneMethods/3179e48a-750b-4051-897c-87b9720928f7/enableSmsSignIn" -Body $json break } "disableSmsSignIn" { Invoke-AzureAdRequest -Method PUT -Query "users/$ObjectId/authentication/phoneMethods/3179e48a-750b-4051-897c-87b9720928f7/disableSmsSignIn" -Body $json break } default { throw "Setting the $($PSCmdlet.ParameterSetName) method is not yet supported." } } } } # Graph Token to use for queries $script:msgraphToken = $null # The API base URI to use for requests $script:baseUri = 'https://graph.microsoft.com/beta/' # Certificate used for authenticating inapplication authentication workflows $script:clientCertificate = $null # Connection Metadata $script:tenantID = '' $script:clientID = '' $script:redirectUri = 'urn:ietf:wg:oauth:2.0:oob' #endregion Load compiled code # SIG # Begin signature block # MIIjkQYJKoZIhvcNAQcCoIIjgjCCI34CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBuNJj4/ZuNldDF # x307fPah37VDc42g9bVE4jRMl2l5hKCCDYEwggX/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/BvW1taslScxMNelDNMYIVZjCCFWICAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg6A2SZ6GX # l8YWuWFuTjwacEGAQ570VarfLLAtYhUVyJUwQgYKKwYBBAGCNwIBDDE0MDKgFIAS # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN # BgkqhkiG9w0BAQEFAASCAQAmK8GjqpGR3R97xVi/azFo/o2cOdVuJOKyVCVHhqY3 # 3vxVKrbmXHxSe6Jgmqs6WH8sTFGHyfA29OUWbHOMcf7e5fl0glwRZKChNSlvx9K5 # 946AuzYforMZt8l0u6HG5rzYT8gSC+FR699Bd6cdXmRDBV79oxi6DMZKlidnO/OA # uHvoLqfluZDFQ4E0aqJwre5DO92p2+1lqutZQ74fHmN3WtSSxqPRDNpzwQ8SZUqe # hdHjklZTaX+eD+3Lu+buT0IxHr/gEm46C++G99s0Z7T2Tf9D3noVz5q1o88i9IKt # lzxiydcjnbwAwQhTaFWVXuPtwb9DAbdlotR1NUsxKDCpoYIS8DCCEuwGCisGAQQB # gjcDAwExghLcMIIS2AYJKoZIhvcNAQcCoIISyTCCEsUCAQMxDzANBglghkgBZQME # AgEFADCCAVQGCyqGSIb3DQEJEAEEoIIBQwSCAT8wggE7AgEBBgorBgEEAYRZCgMB # MDEwDQYJYIZIAWUDBAIBBQAEIDaSrQsVDvRBpL8RkwhyLWVArxMtAOJKkQ4BbPhW # oHaiAgZf25gPgJ4YEjIwMjEwMTE1MDAxOTMxLjIzWjAEgAIB9KCB1KSB0TCBzjEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWlj # cm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBU # U1MgRVNOOkQ5REUtRTM5QS00M0ZFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1T # dGFtcCBTZXJ2aWNloIIORDCCBPUwggPdoAMCAQICEzMAAAEtLk1BymNlM6AAAAAA # AS0wDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw # HhcNMTkxMjE5MDExNTA0WhcNMjEwMzE3MDExNTA0WjCBzjELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWljcm9zb2Z0IE9wZXJh # dGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkQ5REUt # RTM5QS00M0ZFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl # MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqWGN9HVJOphFNLezSLiM # hxIxX4bg3ShiDCVAr6mXgNUwWavWJNkcUuPdO3tXoX4z8FfHSH2LS67XIGeoKo06 # S4kRFNtWczi7cm9HHOxB8KMF+oP8I3Cgw16SjKUgHPE/nRKSOnWk+ydAEodoI/y2 # C69hXOhNDnirZWlgQ//45hNB4Q+pYWLxaCC+xyS56txQaSFhYzwNX/glTs3+tsOu # 1qZht7wu2RWJNBhuKBRIICiv0OG0Bm+rwDQDvdcUfZ1/bAOUu0CcoJyxW9dKZnfl # sCqd43i4RBXLw1B1F4YjW0jpTGgLteeMa8rgxwN0qFq80nsMCdI/n4b8NOR1YP6U # 3wIDAQABo4IBGzCCARcwHQYDVR0OBBYEFNlsZHxCASH4Tg6K/y9DvjTynYbNMB8G # A1UdIwQYMBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRPME0wS6BJoEeG # RWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Rp # bVN0YVBDQV8yMDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUH # MAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljVGltU3Rh # UENBXzIwMTAtMDctMDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYB # BQUHAwgwDQYJKoZIhvcNAQELBQADggEBAH1rA2T3Tqt5wG6g7sTOrsHxQa70SgVe # IvxpzRtuxkMFj3P/enxq1VlELEc3jdrdYZsIxmgpjFIEfpQKRwNzBch80oRtUzOc # XWaOlAQZuqFH6s82oddmi1JX6+fzkDGZ58Azdtwu35Y0GkS45lniQ9lVwW0yjhjJ # CPGg1E+LCan4HQeSFCz+X9UiDRcljqTkVEoT8kURxVjjbno12pRn7eOi7dvg4CS0 # Ta6uvhXpVHDV9986XFlvwzK8Tmaq9NUk5K1XEK6G6qDWsh7yVrWBnmKK4jJZ5+04 # 18zDSdJlyEYuKAN4ifDpd/DCAWcLlCXw9t/aM7EJSW4BhvPKQj4ycGIwggZxMIIE # WaADAgECAgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9v # dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0xMDA3MDEyMTM2NTVaFw0y # NTA3MDEyMTQ2NTVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjAN # BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcRijog7PwTl/X6f2mUa3RU # ENWlCgCChfvtfGhLLF/Fw+Vhwna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBE # D/FgiIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRgMlhgRvJYR4YyhB50 # YWeRX4FUsc+TTJLBxKZd0WETbijGGvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd # /XcfPfBXday9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajyeioKMfDaTgaR # togINeh4HLDpmc085y9Euqf03GS9pAHBIAmTeM38vMDJRF1eFpwBBU8iTQIDAQAB # o4IB5jCCAeIwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyKMZDzQ3t8 # RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIB # hjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fO # mhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9w # a2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr # BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSAB # Af8EgZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcCARYxaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL1BLSS9kb2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEF # BQcCAjA0HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMAdABhAHQAZQBt # AGUAbgB0AC4gHTANBgkqhkiG9w0BAQsFAAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Eh # b7Prpsz1Mb7PBeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcIK1GCRBL7 # uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZLdO9CEMivv3/Gf/I3fVo/HPKZeUqR # UgCvOA8X9S95gWXZqbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8ySif9 # Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoLkSbiOewZSnFjnXshbcOco6I8 # +n99lmqQeKZt0uGc+R38ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+ # Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ732D8OE7cQnfXXSYIghh # 2rBQHm+98eEA3+cxB6STOvdlR3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRy # zR30uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp9cAvVCch98isTtoo # uLGp25ayp0Kiyc8ZQU3ghvkqmqMRZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx # 16HSxVXjad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA12u8JJxzVs341 # Hgi62jbb01+P3nSISRKhggLSMIICOwIBATCB/KGB1KSB0TCBzjELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWljcm9zb2Z0IE9w # ZXJhdGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkQ5 # REUtRTM5QS00M0ZFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2 # aWNloiMKAQEwBwYFKw4DAhoDFQCfzl/Hfod7sXS+CbJSXPbDzaXQsaCBgzCBgKR+ # MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT # HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBBQUAAgUA # 46r/bDAiGA8yMDIxMDExNDIxMzU0MFoYDzIwMjEwMTE1MjEzNTQwWjB3MD0GCisG # AQQBhFkKBAExLzAtMAoCBQDjqv9sAgEAMAoCAQACAhOXAgH/MAcCAQACAhEeMAoC # BQDjrFDsAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEA # AgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQADgYEAapEmDNvHKFoz9GoP # IDX+ENGc3fybhb7HU8fbiyg2rHjnW9RPy3xgRMGD8Yr3u10luc7vxAfzTuTt2RuR # Tk1OnPD3X5aAPsCIPyni/bN5YTBXrCt1Y1VUnRjnCzZOrFpnNA+MURQcZuCIp0at # H/+Hrj+keUC9XHptrhgzFoOCCTkxggMNMIIDCQIBATCBkzB8MQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt # ZS1TdGFtcCBQQ0EgMjAxMAITMwAAAS0uTUHKY2UzoAAAAAABLTANBglghkgBZQME # AgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJ # BDEiBCB8nFN0EE7L6SKQE3XzKftnL4x9smeTNSI9/4gTmxrwITCB+gYLKoZIhvcN # AQkQAi8xgeowgecwgeQwgb0EII7xWnJyfSAHj+KVEA88NtL4KZuqP+4LTXWahzmh # 4YPBMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAEt # Lk1BymNlM6AAAAAAAS0wIgQg5y+28yXnVf9L9ulfLzY0IRx45rxPj5tzoc0Ug2ZX # 17cwDQYJKoZIhvcNAQELBQAEggEAb2VlL745I8KU/wKwaS0zs8FmCOgDhbhaJp5R # 70niUeDsz+58eb8UmPX0nQQTm2ugIwI33rkCYkPJcku5OTKJVR4CGaAWYukFZ9/d # UOvPhIqJJkD2JIlVnnftcfVSWHslUYFvm60vm1cdqnLIgcWBxAqvzA60aKHLXIrA # xEhiVCBqD7U2E76X5HT/LwoSXYj1x3a+lHB7G9Q8yakSpyolsbOcTSCHdOLx0WTR # P37wpExh9ZmmNbrGNNRqH7jsowfQq/rPJRD7YMTrXtwfnOWRsKbqqC4QpJl6WGye # Zaycd/lPPX12Lee5ebBGYJTCJudSKyTvhL4d8WCrsXX1sHocTQ== # SIG # End signature block |