Author Posts

October 22, 2016 at 8:41 pm

Hi all – I have a bunch of servers that need to use the REST API to get/post/delete stuff from an internal webserver (each server needs to self-register/modify/remove itself as appropriate), so it has to be run locally).

This works fine using invoke-webrequest on the PS3 & newer boxes, but a number are running PS2, which won't be upgraded (we are slowly migrating these over to newer VMs). When using System.Net.WebRequest and the same credentials, I consistently get '403 Forbidden' errors. Am I correct in thinking that the credentials aren't even being passed? I've been researching this for ages and trying various settings, but it's hard to find much besides "hey, you should use invoke-webrequest instead." So at this point I've far exceeded my shallow understanding of REST and am pretty much just a monkey on a typewriter. Any help would be appreciated.

PS C:\> # Credentials
$User = "foo"
$PW = "bar"
$SecPW = ConvertTo-SecureString $PW -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential ($User, $SecPW)

PS C:\> # This works! All is well.
Invoke-WebRequest -Uri $URI -Credential $Cred -Method Get -Headers @{ACCEPT="application/json"} | Select StatusCode,StatusDescription,BaseResponse

StatusCode StatusDescription BaseResponse              
---------- ----------------- ------------              
       200 OK                System.Net.HttpWebResponse

PS C:\> # This doesn't work.
$Request = [System.Net.WebRequest]::Create($URI)
$Request.ContentType = "application/json"   
$Request.Credentials = $Cred
$Request.Method = "GET"
$Request.GetResponse()

Exception calling "GetResponse" with "0" argument(s): "The remote server returned an error: (403) Forbidden."
At line:6 char:1
+ $Request.GetResponse()
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : WebException
 

PS C:\> # Nor does this...
$Request = [System.Net.WebRequest]::Create($URI)
$Request.Headers.Add("AUTHORIZATION", "Basic, $Cred")
$Request.PreAuthenticate = $true
$Request.Credentials = $Cred 
$Request.Method = "GET"
$request.ContentType = "application/json"
$Request.GetResponse()

Exception calling "GetResponse" with "0" argument(s): "The remote server returned an error: (403) Forbidden."
At line:8 char:1
+ $Request.GetResponse()
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : WebException

October 24, 2016 at 10:09 pm

The Credentials property of the WebRequest object doesn't accept a PSCredential object, which is what you're passing it. It needs an orange, and you're handing it a Volkswagen ;).

The base System.Net.WebRequest doesn't implement Credentials; that's meant to be implemented by a descendent class (https://msdn.microsoft.com/en-us/library/system.net.webrequest.credentials(v=vs.110).aspx), the docs say, but it wants an ICredentials interface. PSCredential doesn't seem to implement ICredentials.

You might want to use the child class, HttpWebRequest, which does implement Credentials. See https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.credentials(v=vs.110).aspx. You're not really meant to use WebRequest directly.

But this isn't really a PowerShell problem or a REST problem. It's just .NET. So don't feel bad :).

November 1, 2016 at 5:05 pm

Dang. Well, that explains why I still haven't produced the collected works of Shakespeare. I will spend a little while seeing if I can do this, but if not, eh, we install CURL. Bummer! Thanks for the reply; I lost track of this thread. 🙂