Partner Connections Manager authorization code works only once - nest-device-access

I am able to successfully get a PCM authorization code and use it to get a access token but it only works once. Is that the correct behaviour? Seems like it should work indefinitely so the user does not have to continuously authorize a partner. Or once I get a access token I should only use the refresh token afterwards?
Works the first time I request a access token:
Example PCM authorization code:
4/0AY0e-e45jfjsl_KPdjke_BzKgsBirc....
╰─ curl -L -X POST 'https://www.googleapis.com/oauth2/v4/token?client_id=MY-CLIENT-ID&client_secret=MY-CLIENT_SECRET&code=MY-AUTH-CODE&grant_type=authorization_code&redirect_uri=https://www.google.com'
{
"access_token": "ya29.a0AfH6SMAgv...",
"expires_in": 3599,
"refresh_token": "1//04721e...",
"scope": "https://www.googleapis.com/auth/sdm.service",
"token_type": "Bearer"
}
On subsequent tries to use the PCM authorization code it fails. The only way to use it again is to recreate the PCM authorization code.
╰─ curl -L -X POST 'https://www.googleapis.com/oauth2/v4/token?client_id=MY-CLIENT-ID&client_secret=MY-CLIENT_SECRET&code=MY-AUTH-CODE&grant_type=authorization_code&redirect_uri=https://www.google.com'
{
"error": "invalid_grant",
"error_description": "Bad Request"
}

As the payload mentions, the access token expires in an hour and the refresh token should be used to acquire new access tokens as per https://developers.google.com/nest/device-access/authorize.
Note that the refresh token seems to be good for only a week in the sandbox as of this post. At that point you have to re-run the authorization flow.

Related

How to implement a Google Cloud Platform (GCP) Authorization call via HTTP call in postman

I want to implement an HTTP call to Google Cloud Platform (GCP) to generate the Authorization token.
Cant find a the correct GCP documentation for the same as well.
Using the reference from below URL, I was able to generate a Authorizaton token from Postman, using postmans Authorization UI and not the HTTP call UI.
https://www.vulongtran.com/how-to-use-postman-with-google-cloud-platform-apis
And the call to GCP API are working using the token generated from above process.
I tried implementing the same call via HTTP POST request, but not getting expected result.
HTTP POST
URL - https://accounts.google.com/o/oauth2/token
Query param-
grant_type:authorization_code
redirect_uri:https://www.getpostman.com/oauth2/callback
Authorization -
Basic Auth
username -
password -
Headers -
scope:https://www.googleapis.com/auth/cloud-platform
redirect_uri:https://www.google.com
And the response that I get is
400 bad request
{ "error": "invalid_request", "error_description": "Missing required parameter: code" }
2nd Try-
Also tried sending the in the request BODY, like below, but the result was same.
{
grant_type:'authorization_code',
redirect_uri:'https://www.getpostman.com/oauth2/callback'
}
Response
{
"error": "invalid_request",
"error_description": "Missing required parameter: code"
}
I saw another page, where 'code' is used in the call. Dont know what language the code on that page is for.
But I am unable to figure out the correct HTTP call to get the token from there as well.
Google OAuth2: Required parameter is missing: grant_type

Google Classroom API | How add scopes in HTTP request

I want to get a list of courses from an audience by HTTP request, I have set the required areas in the project in Google Cloud, but I still get an error when I try to get the courses.
P.S - Please do not offer me documentation and libraries, do not try to convince me, I just need an HTTP request.
{
"error": {
"code": 403,
"message": "Request had insufficient authentication scopes.",
"status": "PERMISSION_DENIED",
"details": [{
"#type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT",
"domain": "googleapis.com",
"metadata": {
"method": "google.classroom.v1.Courses.ListCourses",
"service": "classroom.googleapis.com"
}
}]
}
}
I tried adding ?scope=https://www.googleapis.com/auth/classroom.courses.readonly to the end of the link
Here is the request template
curl \
'https://classroom.googleapis.com/v1/courses?key=[YOUR_API_KEY]' \
--header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
--compressed
Im going to assume that you are using courses list method
The call should look something like this in raw HTTP Request
GET https://classroom.googleapis.com/v1/courses HTTP/1.1
Authorization: Bearer [YOUR_ACCESS_TOKEN]
Accept: application/json
The access token ([YOUR_ACCESS_TOKEN]) you are sending must be authorized with the proper scope. If you check the documentation page for the method you are using you will see that you should have authorized the user with one of these scopes
So in your case the error Request had insufficient authentication scopes. means that when you requested authorization you did not request one of the scopes above. There for your access token has insufficient authorization scopes to make the request.
The solution is to reauthorize your user with one of the scopes required by the method in question.
You can read more about how to request authorization and what scopes are in the Using OAuth 2.0 to Access Google APIs documentation page.
Hint: Your very first in the oauth2 flow contains the scope.
https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/classroom.courses&response_type=code&redirect_uri=http%3A//127.0.0.1%3A9004&client_id=client_id
This video may help you understand scopes Understanding Google OAuth 2.0 with curl since you appear to be using curl and not just raw HTTP calls.

curl with POST method working, but fetch API return error 503

I have to access a private API (one of Air France flight company's API), and in order to use any of their API, I need an access token.
So in their guide, they say we need to use this cURL to get the token :
$ curl https://www.klm.com/oauthcust/oauth/token -d 'grant_type=client_credentials' -u fakeKey:fakeSecret
TERMINAL
When I execute this cURL in my terminal, and replace the fakeKey and fakeSecret (which I can't give you here unfortunately) by my own, it's working well and I got this answer (with a proper token in place of :
{
"access_token": <TOKEN>,
"token_type":"bearer",
"expires_in":3600
}
POSTMAN
When I do it in Postman, here is what I fill :
URL:
POST: https://www.klm.com/oauthcust/oauth/token
Authorization:
type: Basic Auth
Username: my secret Username
Password: my secret password
Headers:
Authorization: automatically generated from my username and password
Content-Type: application/x-www-form-urlencoded
Body
checked x-www-form-urlencoded
grant_type: client_credentials
That's all, and when I click on SEND, I got my answer and my token.
FETCH / AXIOS / HTTPRequest
So as I am not so good yet in fetching data, I used https://kigiri.github.io/fetch/ to translate from my cURL to a fetch JS method. It return me this code :
fetch("https://www.klm.com/oauthcust/oauth/token", {
body: "grant_type=client_credentials",
headers: {
Authorization: "Basic <HASH_COMPILED_FROM_USERNAME_PASSWORD>",
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST"
})
The <HASH_COMPILED_FROM_USERNAME_PASSWORD> is exactly the same as the one Postman compiled.
So this fetch seems OK for me, however on Chrome it returns a Response for preflight has invalid HTTP status code 503.
Opera is returning me Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin <MY_WEBSITE> is therefore not allowed access. The response had HTTP status code 503.
However it seems weird that the mistake come from their site, I think it's more something that I missed in my fetch request. Do you have an idea ?
Thanks !
Well, the answer finally has been : the request must come from a back-end, otherwise the response won't have anything inside it (or error 503). Thanks #sideshowbarker to your well explaining comments !

Bad Request when using Google OAuth2.0

I am receiving a 400 bad request when using Google OAuth from within Salesforce. The following error is in regards to invalid grant_type, but if you look at the documentation under 'Using Refresh Token' you will see that it is correct.
https://developers.google.com/identity/protocols/OAuth2WebServer
Error:
{
"error": "unsupported_grant_type",
"error_description": "Invalid grant_type: "
}
I am attempting to exchange a refresh_token for an access token and can successfully do it using CURL, with the following code.
curl \
-d refresh_token=REFRESH_TOKEN \
-d client_id=CLIENT_ID \
-d client_secret=CLIENT_SECRET \
-d grant_type=refresh_token https://www.googleapis.com/oauth2/v4/token
The code that I am using inside Salesforce:
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
req.setHeader('Content-Length', '0');
req.setHeader('client_id', 'CLIENT_ID');
req.setHeader('client_secret', 'CLIENT_SECRET');
req.setHeader('refresh_token', 'REFRESH_TOKEN');
req.setHeader('grant_type', 'refresh_token');
req.setEndpoint('https://www.googleapis.com/oauth2/v4/token');
req.setMethod('POST');
return http.send(req);
The -d curl option sends the data in the request body using the application/x-www-form-urlencoded content type which is one of the supported ways of sending those parameters in OAuth2.
-d Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded.
In the Salesforce code you're setting the correct content type, but then are sending the OAuth2 related parameters as additional headers instead of sending them in the request body.
You need to update the code to send the parameters in the request body using the application/x-www-form-urlencoded encoding.
I caught the same issue in fiddler. I added this comment because it may be helpful to somebody.
https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded
Request Body:
code=<some code here>&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code
Goole api response:
{"error": "unsupported_grant_type", "error_description": "Invalid grant_type: "}
The issue occurred because the request body has line breaks between each parameter. if you delete all the line breaks, leaving all values in a single row request will be work fine. e.g. request body:
code=<some code here>&client_id=your_client_id&client_secret=your_client_secret&redirect_uri=https%3A//oauth2.example.com/code&grant_type=authorization_code

Marketo REST API token keeps expiring

I followed the Quick Start Guide on Marketo's site for their REST API. This went well. I was able to get a successful response from their website.
Request:
curl https://ABC-DEF-123.mktorest.com/rest/v1/lists.json?access_token=123:ab
Response:
{"requestId":"123#abcf7aff","result":[],"success":true}
However, when I tried the same request the next day, I received:
{"requestId":"123#abc6731ab6f","success":false,"errors":[{"code":"601","message":"Access token invalid"}]}
I logged into the Marketo admin and noticed that the token I copied and pasted out of the dialog box was different. I tried this new one and it worked.
(This is taken from the guide)
I came across another guide on their site that describes a different authentication process. Marketo Authentication Guide
This guide mentions the token that is returned from the API endpoint has an expiration so I suspect that all Marketo tokens expire (or I need to disable this). However, I have not been able to successfully make requests to this endpoint with my client ID and client secret.
Request:
curl https://ABC-DEF-123.mktorest.com/identity/oauth/token?grant_type=client_credentials&client_id=ACLIENTID&client_secret=ACLIENTSECRET
Response:
{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}
Any help in the right direction would be appreciated. Thanks in advance.
REST API tokens expire. So you typically will need to request a token for each session.
from your specific installed URL, like: MARKETOURL/identity/oauth/tokengrant_type=client_credentials&client_id=abc&client_secret=xyz
Which will result in (example):
{
"access_token": "1234",
"token_type": "bearer",
"expires_in": 3599,
"scope": "email#email.com"
}
You will need to start out your sessions with this request to do subsequent calls. I have code that runs this first and then requests a new token if it expires. The expires_in field is in seconds.
Source: http://developers.marketo.com/documentation/rest/authentication/
I was not able to figure out why my curl requests were failing, but I was able to successfully call the Marketo API with mrkt, a Ruby Gem for Marketo.
I've looked through the logs of what the gem is generating for requests and they appear to be exactly the same. But at least I now successfully calling Marketo.
You need to use following sequences.
grant_type= client_credentials
client_id =you will get Marketo admin where you generate token
client_secret=you will get Marketo admin where you generate token
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
GET <Identity URL>/oauth/token?grant_type=client_credentials&client_id=<Client Id>&client_secret=<Client Secret>
Your first call failed because your token expires every hour currently, according to Marketo's docs.
Your curl call to get a new token failed because curl (or something) was stripping off the auth arguments. Try wrapping the url in quotes.
curl "https://ABC-DEF-123.mktorest.com/identity/oauth/token?grant_type=client_credentials&client_id=ACLIENTID&client_secret=ACLIENTSECRET"
You can get more information about what curl is sending with the -v flag. Running this would have given you enough information to at least know that your entire url wasn't being passed down to the request.
curl -v https://ABC-DEF-123.mktorest.com/identity/oauth/token?grant_type=client_credentials&client_id=ACLIENTID&client_secret=ACLIENTSECRET

Resources