Difference between Invoke-WebRequest, HttpClient Class and WebRequest Class
Hello everyone!
I am trying to send a Client-Certificate authenticated HTTPS-Request to a Web Server.
The only way I was able to get a "200" Response from this Server was with the following code using the Webrequest Class:
using namespace System.Security.Cryptography.X509Certificates
$certPath = '.\client_cert.pfx'
$URI = 'https://example-api.com/api'
$cert = New-Object X509Certificate2($certPath, $certPassword)
# write-host for debugging
Write-Host "Cert Has Private Key: $($cert.HasPrivateKey)"
$request = [System.Net.WebRequest]::Create($URI)
$request.Method = "GET"
$request.ClientCertificates.Add($cert)
$response = $request.GetResponse()
$responseStream = $response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($responseStream)
$responseContent = $reader.ReadToEnd()
$reader.Close()
$responseStream.Close()
$response.Close()
$responseContent
The server responds with "200 - OK" and returns the information wanted.
However I have read that this class is obsolete and that I should rather use the HttpClient Class.
I tried to replicate the above request like so:
using namespace System.Security.Cryptography.X509Certificates
using namespace System.Security.Authentication
using namespace System.Net.Http
using namespace System.Net.Security
$certPath = '.\client_cert.pfx'
$URI = 'https://example-api.com/api'
$cert = New-Object X509Certificate2($certPath, $certPassword)
Write-Host("Cert has private key: ", $cert.HasPrivateKey)
$handler = New-Object HttpClientHandler
$handler.ClientCertificateOptions.Manual
$handler.ClientCertificates.Add($cert)
# write-host for debugging
Write-Host("Client Certificate Options: ", $handler.ClientCertificateOptions)
Write-Host("Client Certificates: ", $handler.ClientCertificates)
$client = New-Object HttpClient($handler)
$client.HttpClientHandler
$response = $client.GetAsync($URI).GetAwaiter().GetResult()
$response
Unfortunately, the server answers with "403 - Forbidden" even though I use the exact same certificate file.
I also tried replicating the call with the built-in cmdlet Invoke-Webrequest like so:
using namespace System.Security.Cryptography.X509Certificates
$certPath = '.\client_cert.pfx'
$URI = 'https://example-api.com/api'
$cert = New-Object X509Certificate2($certPath, $certPassword)
Write-Host("Cert has private key: ", $cert.HasPrivateKey)
$response = Invoke-Restmethod -Method "GET" -URI $URI -Certificate $cert
#$response2 = Invoke-Restmethod -Method "GET" -URI $URI -CertificateThumbprint $cert.Thumbprint
$response
But this also always yields "403 - Forbidden".
Can someone tell me where the mistake is? Because I am clearly missing it.
Why does the obsolete Webrequest Class work, while Invoke-Webrequest Cmdlet and HttpClient Class don't?