Google API - Oauth Refresh Token - Powershell - 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.

Related

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

Azure media service job creation fails using rest api

Trying to consume Azure media service rest api. (following the tutorial : https://learn.microsoft.com/en-us/azure/media-services/media-services-rest-get-started)
Everything works fine until the point I try to create a Job. Sending the same request as in example (except asset id and token) and getting response :
Parsing request content failed due to: Make sure to only use property names that are defined by the type
Request:
POST https://wamsdubclus001rest-hs.cloudapp.net/api/Jobs HTTP/1.1
Connection: Keep-Alive
Content-Type: application/json
Accept: application/json; odata=verbose
Accept-Charset: UTF-8
Authorization: Bearer token -> here i send real token
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
x-ms-version: 2.11
Content-Length: 458
Host: wamsdubclus001rest-hs.cloudapp.net
{
"Name":"TestJob",
"InputMediaAssets":[
{
"__metadata":{
"uri":"https://wamsdubclus001rest-hs.cloudapp.net/api/Assets('nb%3Acid%3AUUID%3A5168b52a-68ed-4df1-bac8-0648ce734ff6')"
}
}
],
"Tasks":[
{
"Configuration":"Adaptive Streaming",
"MediaProcessorId":"nb:mpid:UUID:ff4df607-d419-42f0-bc17-a481b1331e56",
"TaskBody":"<?xml version=\"1.0\" encoding=\"utf-8\"?><taskBody><inputAsset>JobInputAsset(0)</inputAsset> <outputAsset>JobOutputAsset(0)</outputAsset></taskBody>"
}
]
}
Response:
{
"error":{
"code":"",
"message":{
"lang":"en-US",
"value":"Parsing request content failed due to: Make sure to only use property names that are defined by the type"
}
}
}
It seems to be related with __metadata property. when I follow instruction from here : Creating Job from REST API returns a request property name error, the error changes:
"error":{
"code":"",
"message":{
"lang":"en-US",
"value":"Invalid input asset reference in TaskBody - "
}
}
}
Cant figure out whats wrong, thanks
Let me check on this, but it could be a couple issues that I have run into in the past.
First. Set both the Accept and Content-Type headers to:
"application/json; odata=verbose"
Next, double check that you are actually using the long underscore character on the metadata property. I've had issues where that was sending the wrong underscore character and it didn't match the property name.
Let me know if either of those helps.
It seems the issue was about "Content-Type". As I am using .net Core it was not easy to set the Conent-type as "application/json; odata=verbose".
1) Tried with RestSharp - dosnt support it, it cuts "odata=verbose" part out
2) Tried with Systsem.Net.Http.HttpClient -> Possible but difficult.
To add it as "Accept" :
MediaTypeWithQualityHeaderValue mtqhv;
MediaTypeWithQualityHeaderValue.TryParse("application/json;odata=verbose", out mtqhv);
client.DefaultRequestHeaders.Accept.Add(mtqhv);//ACCEPT header
To add it as "Content-Type" :
request.Content = new StringContent(content,
System.Text.Encoding.UTF8); //CONTENT-TYPE header -> default type will be text/html
request.Content.Headers.Clear(); // need to clear it - it will fail otherwise
request.Content.Headers.TryAddWithoutValidation("Content-Type","application/json;odata=verbose");

Can't turn curl into Invoke-WebRequest

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