LinkedIn API metrics - linkedin

#linkedin
I am trying in python to get the metrics (likes, shares, comments, etc) of my company page.
We registered the API which includes Marketing Developer Platform.
I understand, I need Members authentication and I set up Oauth 2.0 settings.
I've created the access_token for the permissions (among them is r_organization_social - which I need to collect data).
What is confusing for me, how to use this token.
Is it enough to use it together with header in my request?
response = requests.get('https://api.linkedin.com/v2/posts', headers = headers)
I've created the header like this:
headers = {
'Authorization': f'Bearer {access_token}',
'cache-control': 'no-cache',
'X-Restli-Protocol-Version': '2.0.0'
}
I tried that and I am getting an error that token is Invalid, even though it is live and active for the next 11 months.
I also tried many things where I would first send request for authenticate my request and then manually copy the response to get the new access token.
That access token never worked - was invalid.
Even if it works, looks like that wouldn't be acceptable solution...
Can you please help with this?
Thanks

The following is working for me.
I used this format of the header:
headers = {
'X-Restli-Protocol-Version': '2.0.0',
'Authorization': 'Bearer '+ access_token }
payload ={}
And the request looks like this (instead of posts I use ugcPosts):
requests.request("GET",'https://api.linkedin.com/v2/ugcPosts?q=authors&authors=List('+urnLiOrganizationEncode + ')&count=100', headers=headers,data=payload)

Related

Browser not saving cookie sent by Golang backend

I know this question has been asked a bunch of times, but I tried most of the answers and still can't get it to work.
I have a Golang API with net/http package and a JS frontend. I have a function
func SetCookie(w *http.ResponseWriter, email string) string {
val := uuid.NewString()
http.SetCookie(*w, &http.Cookie{
Name: "goCookie",
Value: val,
Path: "/",
})
return val
}
This function is called when the user logs in, and I expect it to be sent to all the other endpoints. This works as expected with Postman. However, when it comes to the browser, I can't seem to get it to remember the cookie or even send it to other endpoints.
An example of JS using an endpoint
async function getDataWithQuery(query, schema){
let raw = `{"query":"${query}", "schema":"${schema}"}`;
let requestOptions = {
method: 'POST',
body: raw,
redirect: 'follow',
};
try{
let dataJson = await fetch("http://localhost:8080/query/", requestOptions)
data = await dataJson.json();
}catch(error){
console.log(error);
}
return data;
}
I tried answers like setting SameSite attribute in Golang, or using credential: "include" in JS with no luck.
Thanks to the discussion in the comments, I found some hints about the problem.
Saving cookies (both API and frontend on the same host)
I used document.cookie to save the cookie. I set the options by hand since calling res.cookie on the response of the API fetch only returned the value. An example is document.cookie = `goCookie=${res.cookie}; path=/; domain=localhost;.
Sending cookies
This has been answered before in previous questions and answered again in the comments. The problem was that I used credential:'include' instead of the correct credentials:'include' (plural).
CORS and cookies
In case the API and the frontend are not on the same host you will have to modify both the API and the frontend.
frontend
The cookie has to have the domain of the API since it's the API that requires it, not the frontend. So, for security reasons, you can't set a cookie for a domain (API) from another domain (frontend). A solution would be redirect the user to an API endpoint that returns Set-Cookie header in the response header. This solution signals the browser to register that cookie with the domain attached to it (the API's domain, since the API sent it).
Also, you still need to include credentials:'include' in the frontend.
API
You will need to set a few headers. The ones I set are
w.Header().Set("Access-Control-Allow-Origin", frontendOrigin)
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, withCredentials")
w.Header().Set("Access-Control-Allow-Methods", method) // use the endpoint's method: POST, GET, OPTIONS
You need to expose the endpoint where the frontend will redirect the user and set the cookie in the response. Instead of setting the domain of the API by hand, you can omit it, the browser will fill it with the domain automatically.
To handle the CORS and let JS send the cookie successfully, you will have to set the SameSite=None and Secure attributes in the cookie and serve the API over https (I used ngrok to make it simple).
Like so
func SetCookie(w *http.ResponseWriter, email string) string {
val := uuid.NewString()
http.SetCookie(*w, &http.Cookie{
Name: "goCookie",
Value: val,
SameSite: http.SameSiteNoneMode,
Secure: true,
Path: "/",
})
// rest of the code
}
I recommend you also read the difference between using localStorage and document.cookie, it was one of the problems I had.
Hope this helps.

Meteor js requestPermissions not working

Meteor js requestPermissions not working. I want to access google calendar, access token not permission with google calendar. How I can get access google calendar.
there are two things to consider. The right permission you need from google, and the API you use to access your data. You don't provide too many details so I don't know whether you need mobile (Cordova) too.
For your project, in Google Developer Console you need to enable the Calendar API. Once you do that, you have options to see what appId / authorization is relevant for your API so you add it to your Meteor Settings.
Then from the OAuth 2.0 scopes you need to select the exact scope you need (search for "calendar" for instance) and add that scope (the entire url) to your array of scopes.
Then you can do GET or POST with something like the native HTTP API of Meteor
example:
let data = HTTP.call('GET', `https://people.googleapis.com/v1/people/me/connections?pageToken=${res.data.nextPageToken}&personFields=emailAddresses`,
// let data = HTTP.call('GET', `https:https://www.googleapis.com/calendar/v3/calendars/{... your calendarId} `,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json'
}
},
(err, res) => { handle these })

Can't access FireBase Database via HTTP/REST error 403 Forbidden

Swift + Vapor framework for server + Xcode 8.1
I am trying to read Firebase Realtime Database making HTTP requests to my DB, but I get permission denied.
These are the steps:
1. create JWT sign it with secret key downloaded from "console.developers.google.com"
2. send POST request to OAuth2 server and get access token
3. send GET request to firebase database with access token received from OAuth2 server.
I get "Permission denied", HTTP/1.1 403 Forbidden
// the header of the JSON Web Token (first part of the JWT)
let headerJWT = ["alg":"RS256","typ":"JWT"]
// the claim set of the JSON Web Token
let jwtClaimSet =
["iss":"firebase-adminsdk-kxx5h#fir-30c9e.iam.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/firebase.database", //is this the correct API to access firebase database?
"aud":"https://www.googleapis.com/oauth2/v4/token",
"exp": expDate,
"iat": iatDate]
drop.get("access") { request in
var accesstoken = "ya29.ElqhA-....XXXX"
let responseFirebase = try drop.client.get("https://fir- 30c9e.firebaseio.com/data/Users.json",
headers: ["Authorization":"Bearer \(accesstoken)"],
query: [:])
print("FirebaseResponse_is \(responseFirebase)")
return "success"
}
TLDR; Try placing auth=<TOKEN> in your query string instead of using the authorization header.
The Firebase documentation is unclear on how this works. According to the documentation, there are three methods that should work.
auth=<TOKEN> in query string (link)
access_token=<TOKEN> in query string (link)
Authorization: Bearer <TOKEN> in request header (link)
I'm not convinced that all three methods do actually work however. I'm using method 1 in my application, so I know that one works for sure.
The scope key was missing value https://www.googleapis.com/auth/userinfo.email
let jwtClaimSet =
["iss":"firebase-adminsdk-kxx5h#fir-30c9e.iam.gserviceaccount.com",
"scope": "https://www.googleapis.com/auth/firebase.database
https://www.googleapis.com/auth/userinfo.email",
"aud":"https://www.googleapis.com/oauth2/v4/token",
"exp": expDate,
"iat": iatDate]
I found the answer browsing google groups here
headers: ["Authorization":"Authorization: Bearer \(accesstoken)"],
should be
headers: ["Authorization":"Bearer \(accesstoken)"],

How to use Google Contacts API in meteor?

I am using meteor to create a webpage with a dropdown list of Google Groups to select from and once selected, the Google contacts will be displayed.
I am using HTTP.call POST to Google's API and testing with the accessToken from mongoDB but when I use that token after some time it expires. I looked into implementing an authentication flow but it is getting very complicated since there is no sample code on Google for meteor. I am new to nodeJS, Javascript and Meteor. Am I going about this the wrong way? How would I implement this in meteor?
https://developers.google.com/accounts/docs/OAuth2?csw=1#expiration
To deal with the expiration of the accessToken, you will need to obtain the refreshToken from Google. With this refreshToken, you can obtain a new accessToken whenever necessary via a simple HTTP POST to Google's API. Here is the relevant documentation from Google. To obtain the refreshToken, you will need to request for offline access and may also need to force the approval prompt, as detailed in this SO post.
forceApprovalPrompt: {google: true},
requestOfflineToken: {google: true},
I recommend achieving all of the above using Meteor's HTTP package. All the tools are there. You've probably already figured it out:
var result = HTTP.post(
"https://www.googleapis.com/oauth2/v3/token",
{
params: {
'client_id': config.clientId,
'client_secret': config.secret,
'refresh_token': user.services.google.refreshToken,
'grant_type': 'refresh_token'
}
});
//Do some error checking here
var newAccessToken = result.data.access_token;
refresh_token - The refresh token returned from the authorization
code exchange.
client_id - The client ID obtained from the
Developers Console.
client_secret - The client secret obtained from
the Developers Console.
grant_type - As defined in the OAuth 2.0
specification, this field must contain a value of refresh_token.
result.data will be a JSON object with the following
{
"access_token":"1/fFBGRNJru1FQd44AzqT3Zg",
"expires_in":3920,
"token_type":"Bearer",
}
Have a look at this package its a little wrapper that does auto refresh for you:
here
I actually ended up building my own auth flow for with oauth handler because i needed to move away from a tokens linked to user profiles.

400 (Bad Request) when requesting GA API

I got a 400 Bad Request when trying to access Google Auth. I am using the demo code in this article:
https://developers.google.com/analytics/solutions/articles/hello-analytics-api
The address I am requesting is:
https://accounts.google.com/o/oauth2/auth?client_id=875938******.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fanalytics.readonly&immediate=true&include_granted_scopes=true&proxy=oauth2relay452650337&redirect_uri=postmessage&origin=http%3A%2F%2Flocalhost%3A8080&response_type=token&state=895891795%7C0.1215960807&authuser=0
I have successfully created my own ClientId and Keys.
Is there anything I need to take care of?
Thanks,
There are several things wrong with your request. First the scope, second the respons_type. I'm not sure where on the page you linked that you found that example. You should really try and find a library for what ever language you are using it will make it easer. But if you want to know the exact URLs you should be posting they should look something like this.
The initial URI to request that the user give you access to there account should look like this In this case the scope notice my scope is different then yours and I'm requesting a code:
https://accounts.google.com/o/oauth2/auth?client_id={clientid}.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/analytics.readonly&response_type=code
Once they say yes you take the authentication Code you got from the above request and Post it back to request an access_token and a refresh_token
https://accounts.google.com/o/oauth2/token
code=4/X9lG6uWd8-MMJPElWggHZRzyFKtp.QubAT_P-GEwePvB8fYmgkJzntDnaiAI&client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code
this is the response:
{
"access_token" : "ya29.1.AADtN_VSBMC2Ga2lhxsTKjVQ_ROco8VbD6h01aj4PcKHLm6qvHbNtn-_BIzXMw",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/J-3zPA8XR1o_cXebV9sDKn_f5MTqaFhKFxH-3PUPiJ4"
}
The accesstoken you get from the above request is what you will be using to make requests to the service. After one hour your access token will have expired you will need to request a new access token you take the refreshtoken that you got above and post it to :
https://accounts.google.com/o/oauth2/token
client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token
This is the response:
{
"access_token" : "ya29.1.AADtN_XK16As2ZHlScqOxGtntIlevNcasMSPwGiE3pe5ANZfrmJTcsI3ZtAjv4sDrPDRnQ",
"token_type" : "Bearer",
"expires_in" : 3600
}
Hope this helps.

Resources