Can't turn curl into Invoke-WebRequest - powershell

I've got a curl command that works great and I'm trying to turn it into a PowerShell Invoke-WebRequest call.
Here's the working curl with the multipart POST data:
curl -X POST "http://domain.com/admin/batchOrder/processBatch"
-F "ordersFile=#c:\temp\Sample_Auto_Order_Input_File.xml"
-F "psid=3002010250764"
-F "recipients[0]=astraljack#example.com"
And here's where I'm trying to do it via Invoke-WebRequest. Based on what I've read, I need to create a hash table of name-value pairs. I feel like I should be creating the hash table just like I do the multipart POST data above.
$form.clear()
$form.Add("ordersFile", "c:\temp\Sample_Auto_Order_Input_File.xml")
$form.Add("psid", "3002010250764")
$form.Add("recipients[0]", "astraljack#example.com")
$form
Then I can call Invoke-WebRequest.
Invoke-WebRequest http://domain.com/admin/batchOrder/processBatch -Body $form -Method Post
This fails with a 400 Bad Request. To be clear, I've never gotten this Invoke-WebRequest to work so I could be way off base here. I'm not even sure where I can look for a better error msg.
If it helps, the contents of the exception are
IsMutuallyAuthenticated : False
Cookies : {}
Headers : {Connection, Transfer-Encoding, Content-Type, Date...}
SupportsHeaders : True
ContentLength : -1
ContentEncoding :
ContentType : application/json;charset=UTF-8
CharacterSet : UTF-8
Server : Apache
LastModified : 5/12/2014 10:23:19 AM
StatusCode : BadRequest
StatusDescription : Bad Request
ProtocolVersion : 1.1
ResponseUri : http://domain.com/admin/batchOrder/processBatch
Method : POST
IsFromCache : False

The best way to solve the problem is to go download Fiddler and then capture the CURL request. Inspect its RAW request. Then do the same for the Invoke-WebRequest command. See what is different and that should tell you what you need to tweak with Invoke-WebRequest.

The #filepath syntax in curl actually reads the contents of the file into the parameter, but in your PowerShell version you are just setting the value of ordersFile to the filename. Try:
$form.clear()
$form.Add("ordersFile", (get-content "c:\temp\Sample_Auto_Order_Input_File.xml"))
$form.Add("psid", "3002010250764")
$form.Add("recipients[0]", "astraljack#example.com")
$form
Also, you may need to add -ContentType "application/x-www-form-urlencoded" to your Invoke-WebRequest call.
`

I know this is an old question, but I figured since it was still unanswered, I'd throw in my two cents. Here's how I would do this:
$form = #{
'ordersFile' = 'c:\temp\Sample_Auto_Order_Input_File.xml'
'psid' = '3002010250764'
'recipients[0]' = 'astraljack#example.com'
}
Invoke-WebRequest -Uri "http://domain.com/admin/batchOrder/processBatch" -Body $form -Method Post

Related

Google API - Oauth Refresh Token - Powershell

I'm writing a script that will download Google sheets using an Oauth access token. The script works just fine, but I'm having issues refreshing my access token.
Every guide I have found online shows me some iteration of the following:
$refreshTokenParams = #{
client_id=$clientId;
client_secret=$secret;
refresh_token=$refreshToken;
grant_type='refresh_token';
}
$refreshedToken = Invoke-WebRequest -Uri "https://accounts.google.com/o/oauth2/token" -Method POST -Body $refreshTokenParams
$accesstoken = $refreshedToken.access_token
When I run this script it returns the following:
StatusCode : 200
StatusDescription : OK
Content : <!doctype html><html lang="en" dir="ltr"><head><base href="https://accounts.google.com/"><script data-id="_gd" nonce="<Hidden just in case>">window.WIZ_global_data =
{"Mo6CHc":-<Hidden just in case>,"O...
RawContent : HTTP/1.1 200 OK
X-Frame-Options: DENY
Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
google-accounts-embedded: 1
Pragma: no-cache
Transfer-Encoding: chunked
Strict-Transport-Security: max-...
Forms : {}
Headers : {[X-Frame-Options, DENY], [Vary, Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site], [google-accounts-embedded, 1], [Pragma, no-cache]...}
Images : {}
InputFields : {}
Links : {#{innerHTML=Learn more; innerText=Learn more; outerHTML=Learn more;
outerText=Learn more; tagName=A; href=https://developers.google.com/identity/protocols/oauth2; target=_blank; jsname=erTfTe}, #{innerHTML=Help; innerText=Help; outerHTML=<A
href="https://support.google.com/accounts?hl=en" target=_blank>Help</A>; outerText=Help; tagName=A; href=https://support.google.com/accounts?hl=en; target=_blank},
#{innerHTML=Privacy; innerText=Privacy; outerHTML=<A href="https://accounts.google.com/TOS?loc=US&hl=en&privacy=true" target=_blank>Privacy</A>; outerText=Privacy;
tagName=A; href=https://accounts.google.com/TOS?loc=US&hl=en&privacy=true; target=_blank}, #{innerHTML=Terms; innerText=Terms; outerHTML=<A
href="https://accounts.google.com/TOS?loc=US&hl=en" target=_blank>Terms</A>; outerText=Terms; tagName=A; href=https://accounts.google.com/TOS?loc=US&hl=en; target=_blank}}
ParsedHtml : System.__ComObject
RawContentLength : 1759969
When I save this output to an HTML file, I get this
Error 400: invalid_request
The error says "Required parameter is missing: response_type"
This Google doc mentions response_type='code' and I've added that to my array and that had no impact.
I feel like this section in the guide SHOULD work, but it doesnt. Unless maybe I'm implementing it wrong?
I have tried using "Invoke-restmethod" while specifying the content type to json/application, I've used alternative URIs and I've quadruple checked my client ID and password. I have no idea what I'm doing wrong.
If anyone has experience with refreshing Oauth access tokens using Powershell I would really appreciate your help.
Thanks in advance
I wrote this a while ago for gmail api GmailSendMail.psi
The issue is how you are sending the post body. It needs to be in the query parameters format.
function RefreshAccessToken([string]$clientId,[string]$secret, [string]$refreshToken){
$data = "client_id=$clientId&client_secret=$secret&refresh_token=$refreshToken&grant_type=refresh_token"
try {
$response = Invoke-RestMethod -Uri https://www.googleapis.com/oauth2/v4/token -Method POST -Body $data
return $response.access_token;
} catch {
# Dig into the exception to get the Response details.
# Note that value__ is not a typo.
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
}
}
Let me know if you have any issues i will see if i cant update it for you.

Differentiate invoke-WebRequest status codes

I am attempting to validate URLs prior to downloading those files, and I want to differentiate between things like a path that requires credentials vs a bad path.
I have this at the moment
function Get-UrlStatusCode([string] $Url) {
try {
return (Invoke-WebRequest -Uri $Url -UseBasicParsing -DisableKeepAlive -Method:head).StatusCode
} catch [Net.WebException] {
return "$([Int]$_.Exception.Response.StatusCode) $($_.Exception.Response.statusDescription)"
}
}
(Get-UrlStatusCode 'http://AWSBUCKETPATH/Test_Public.xml')
(Get-UrlStatusCode 'http://AWSBUCKETPATH/Test_Private.xml')
(Get-UrlStatusCode 'http://AWSBUCKETPATH/Test_Missing.xml')
For the public path I am getting the expected StatusCode of 200, but both the private and the missing examples are returning 403 Forbidden. Is this a failure in my code, or something that needs to be configured at AWS to provide a 404 Not Found for the bad path, or is this just not something that is possible despite the existence of 404 as a code?

Teams Webhook error: Invoke-RestMethod: Bad payload received by generic incoming webhook

I'm using configured Teams webhook in my Powershell script and keep encountering the mentioned error message. What's strange, is that this exact method of configuring Webhook worked a few months ago on a different script.
Here's what I'm trying to do:
#Set URI of the Teams channel Webhook
$URI = 'https:....'
#Define Rest Method Parameters for the Teams Webhook sending
$RestMethodParameters = #{
"URI" = $URI
"Method" = 'POST'
"Body" = $null
"ContentType" = 'application/json'
}
$JSONBody = #{
"#type" = "MessageCard"
"#context" = "http://schema.org/extensions"
"themeColor" = '0078D7'
}
#Adding text to title and body
$JSONBody += #{
"title" = "'costReport-func' Function for connecting AzAccount has failed"
"text" = "Function failed at connection to AzAccount step."
}
#Sending the message to Teams
($RestMethodParameters).Body += ConvertTo-Json $JSONBody
Invoke-RestMethod #RestMethodParameters
And with this I'm getting "Bad payload received by generic incoming webhook." error message. What is causing the issue here?
Update: Microsoft has released a preview version (2.1.0) of the Teams PowerShell module which works properly with modern authentication. It’s likely that this version will be pushed through to general availability quite quickly.
Please go through this link for more information.

How to using powershell, download and save the recieved user photo from microsoft Graph API

$apiUrl = "https://graph.microsoft.com/v1.0/me/photo/$value"
Invoke-RestMethod -Headers #{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $apiUrl -Method Get
This gets me a response like below:
#odata.context : https://graph.microsoft.com/v1.0/$metadata#users('48db12f7-f809-4ff0-a55c-ab05e135c092')/photo/$entity
#odata.mediaContentType : image/jpeg
#odata.mediaEtag : "D4976167"
id : 360X360
height : 360
width : 360
i am not getting a way on how to go for next step.
my objective is to:
1. Save the photo to a variable ( i believe as a byte array). or
2. Or get the photo directly downloaded to a .jpeg file.
Finally from another question in here i could figure out the problem with my code.
The solution was to escape the $value at the end of the url with `$value

Extract Response Data from Invoke-RestMethod

I have this piece of code which creates a new ticket in ServiceNow
$Response = Invoke-RestMethod -Uri $URI -Credential $SNowCreds -Method Post -Body $body -ContentType 'application/xml'
Write-IntoLog $Response.result
The output is stored in $Response and is as below
#{parent=; made_sla=true; caused_by=; watch_list=; upon_reject=Cancel all future Tasks; sys_updated_on=2018-01-11 08:49:50; child_incidents=0; hold_reason=; approval_history=; number=INC0010079; resolved_by=; sys_updated_by=Admin; opened_by=; user_input=; sys_created_on=2018-01-11 08:49:50; sys_domain=; state=In Progress; sys_created_by=Admin; knowledge=false; order=; calendar_stc=; closed_at=; cmdb_ci=; delivery_plan=; impact=2 - Medium; active=true; work_notes_list=; business_service=; priority=2 - High; sys_domain_path=/; rfc=; time_worked=; expected_start=; opened_at=2018-01-11 08:49:50; business_duration=; group_list=; work_end=; caller_id=; reopened_time=; resolved_at=; approval_set=; subcategory=Internal Application; work_notes=; short_description=Issues with Accessing Web URL; close_code=; correlation_display=; delivery_task=; work_start=; assignment_group=; additional_assignee_list=; business_stc=; description=We are facing issues with accessing the portal https://www.inmotion.com. The error Received is a 403 Error and Access to the same; calendar_duration=; close_notes=; notify=Do Not Notify; sys_class_name=Incident; closed_by=; follow_up=; parent_incident=; sys_id=2c40df9edb234300479a7e7dbf96198f; contact_type=; reopened_by=; incident_state=In Progress; urgency=1 - High; problem_id=; company=; reassignment_count=0; activity_due=UNKNOWN; assigned_to=; severity=3 - Low; comments=; approval=Not Yet Requested; sla_due=UNKNOWN; comments_and_work_notes=; due_date=; sys_mod_count=0; reopen_count=0; sys_tags=; escalation=Normal; upon_approval=Proceed to Next Task; correlation_id=; location=; category=Network}
From the output I want to extract the number(Incident ID) and also generate a link to the ServiceNow Incident.
However I am unable to extract the number(Incident ID). I tried converting the piece of output to JSON
$Response = Invoke-RestMethod -Uri $URI -Credential $SNowCreds -Method Post -Body $body -ContentType 'application/xml' | ConvertTo-Json
I tried to navigate it through the nodes. I am still not able to retrieve the IncidentID
Request your assistance in the above issue.
Without using the 'ConvertTo-Json'
Write-host "The number is $($response.result.number)"
This works.
Other useful reference:
Powershell ServiceNow API