Implementing auto-post in linkedin using spring boot - java

I am implementing auto-post feature in linkedin using spring boot and oauth2. I have created the app in linkedin and the permissions it request are r_liteprofile, w_member_social. I am able to get access_token but when i am sending POST request to https://api.linkedin.com/v2/ugcPosts along with the token then the server is responding with 403 Forbidden status. What am i doing wrong?
Does we need any more permission than r_liteprofile, w_member_social to post in linkedin?
TokenResponse tokenResponse = gson.fromJson(token, TokenResponse.class);
String post_url = "https://api.linkedin.com/v2/ugcPosts";
HttpPost wallPost = new HttpPost(post_url);
ArrayList mediaList = new ArrayList();
wallPost.setHeader("Content-Type","application/json");
wallPost.setHeader("Authorization","Bearer "+tokenResponse.getAccess_token());
wallPost.setHeader("X-RestLi-Protocol-Version","2.0.0");
I have used HttpClient to send the request along with above headers.
The following image shows the token and permissions.

There is nothing wrong with the OAuth token as if there was the response would be 401 (https://developer.linkedin.com/docs/v2/oauth2-client-credentials-flow)
I think you need to add 'w_share' scope to your application. Current scopes do now allow posting updates to LinkedIn. See details here: https://learn.microsoft.com/en-us/linkedin/shared/references/migrations/default-scopes-migration

Related

How to build logout request using okhttp?

I am using Simple_JWT for authentication in Djangorestframework back-end. when a user is logged in the following url will log them out:
http://130.50.85.130/rest-auth/logout/
it requires no data.
now I am trying to post similar request using Okhttp.
When I am trying the following, it breaks:
Request post_request = new Request.Builder()
.url(url_str)
.addHeader("Authorization", "JWT "+token)
.build();
Note that it doesn't have a body and it has token in the header. I am not sure if this post request needs any body or needs header containing token.
I guess the bottom line of my question is how to send a request for log out using okhttp from a user that is already signed in,
Please advise,
Thanks,

Spring - oauth2 - exchange authorization code for refresh and access tokens

I want to exchange authorization code for refresh and access tokens with Spring oauth2 client package. My code looks like:
public static void main(String[] args) {
AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails();
resource.setUserAuthorizationUri("http://localhost:8080/oauth/authorize");
resource.setAccessTokenUri("http://localhost:8080/oauth/token");
resource.setClientId("my-client-with-secret");
resource.setClientSecret("secret");
AccessTokenRequest request = new DefaultAccessTokenRequest();
request.setAuthorizationCode("o9subu");
AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider();
OAuth2AccessToken accessToken = provider.obtainAccessToken(resource, request);
System.out.println(accessToken.getValue());
}
The provider is from https://github.com/spring-projects/spring-security-oauth/tree/master/tests/annotation/approval and I've taken the temp oauth2 code from the browser when I called the provider directly.
And the error message is
Exception in thread "main" error="invalid_request", error_description="Possible CSRF detected - state parameter was required but no state could be found"
at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getParametersForTokenRequest(AuthorizationCodeAccessTokenProvider.java:255)
at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:209)
I still want to request for access_token and secret_token by myself because I obtain the oauth2 code from another system.
First of all, to get the refresh_token you must have got a code that will let you get it, to do that set "&access_type=offline&approval_prompt=force" inside the url you send to get the code.
Then you can ask for refresh_token setting this parameters
code=your_code_generated
client_id=your_client_id
client_secret=your_client_secret
redirect_uri=https://oauth2.example.com/code
grant_type=authorization_code
POST https://accounts.google.com/o/oauth2/token
You can see more detail in Google Identity Platform https://developers.google.com/identity/protocols/OAuth2WebServer
Simple add this line after the set Authorization Code:
request.setPreservedState(new Object());

Google Play Developer API - Query purchase token returns Invalid Value

I am trying to set up a web service to query Google Play purchases. We store the order information for customers and this service would call Google Play API to query the subscription details.
Every time i try to query a purchase, it gives me the error:
HTTP/1.1 400 Bad Request
{
"error":{
"errors":[
{
"domain":"global",
"reason":"invalid",
"message":"Invalid Value"
}
],
"code":400,
"message":"Invalid Value"
}
}
Here is what I tried:
Created a project in https://console.developers.google.com enabled the "Google Play Android Developer API"
Created an oAuth 2.0 client_id and client_secret for type Web application
Logged in as the account owner, I generated a refresh_token
In https://play.google.com/apps/publish I went to Settings -> API Access and linked the the project to my app
Code wise, I used the refresh_token to get an access_token:
String refreshToken = "1/ljll6d9ME3Uc13jMrBweqXugV4g4timYcXXXXXXXXX";
HttpPost request = new HttpPost("https://accounts.google.com/o/oauth2/token");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("client_id", client_id));
params.add(new BasicNameValuePair("client_secret", client_secret));
params.add(new BasicNameValuePair("refresh_token", refreshToken));
params.add(new BasicNameValuePair("grant_type", "refresh_token"));
request.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity);
JSONObject json = new JSONObject(body);
String accessToken = json.getString("access_token");
The access_token from this works because i can call this API with it and get the response back:
String url = String.format("https://www.googleapis.com/androidpublisher/v2/applications/%s/inappproducts/%s", packageName, productId);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
get.setHeader("Authorization", "Bearer " + accessToken);
HttpResponse response = client.execute(get);
// parse response etc...
This returns:
{
"packageName":"com.my.app",
"sku":"com.my.app.premium",
"status":"active",
"purchaseType":"subscription",
"defaultPrice":{
//...
}
},
"listings":{
"en-US":{
"title":"My App Premium",
"description":"My App"
}
},
"defaultLanguage":"en-US",
"subscriptionPeriod":"P1Y"
}
Now, I want to get informatoin about a purchase. I have a information from a purchase as such:
{
"orderId":"GPA.1111-1111-1111-11111",
"packageName":"com.my.app",
"productId":"com.my.app.premium",
"purchaseTime":1452801843877,
"purchaseState":0,
"developerPayload":"XXXXXXXd9261023a407ae5bb6ab8XXXXXXX",
"purchaseToken":"xxxxxxxxxxxxxx.YY-J123o12-xxxxxxxxxxxxxxxmYRk2itBkNdlXhyLMjXsxxxxxxxxxxxxLfBxabaAjKbeBC0PVhHnHd1DDbFkgZtbQxxk5pDIAH3xBHu8HrcWfRgewAYnFeW9xxxxxxxxxxxxxC5TDjcBL8fhf",
"autoRenewing":true
}
String url = String.format("https://www.googleapis.com/androidpublisher/v2/applications/%s/purchases/products/%s/tokens/%s",packageName, productId, purchaseToken);
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
get.setHeader("Authorization", "Bearer " + accessToken);
HttpResponse response = client.execute(get);
// parse response etc...
Since the packageName / productId and access_token seem to work for the first call, and the purchaseToken is right out of the order info. What is giving the invalid value error?
Any help appreciated - not sure what else to try. Thanks!
UPDATE:
I went through and validated all the package names and account setup
The real issue seemed to be the service i was hitting. I switched it to:
https://www.googleapis.com/androidpublisher/v2/applications/packageName/purchases/subscriptions/subscriptionId/tokens/purchaseToken
I also swapped to use the Google Client API as it was much cleaner looking that manually creating requests.
Thanks for help and replies
First I want to share with you what is 400 bad request and what is the
real cause for occuring it?
Ans: It indicates that the query was invalid. E.g., parent ID was missing or the combination of dimensions or metrics requested was not valid.
Recommended Action: You need to make changes to the API query in order for it to work.
Resource Link: Standard Error Responses
Your problem:
Your code was running properly and returning related json file as output. But after a period,it is not working when you want to get information about purchase. It gives error message "HTTP/1.1 400 Bad Request"
Root cause:
For refresh token, the response always includes a new access token. A response is shown below:
{
"access_token":"1/fFBGRNJru1FQd44AzqT3ZgXXXXXX",
"expires_in":3920,
"token_type":"Bearer",
}
So, access token has a expiry time. after a expiry time, the access token will not work.
There is another restriction also. There are limits on the number of refresh tokens that will be issued; one limit per client/user combination, and another per user across all clients.
So, in your case, you have already crossed your limit of creating refresh token.
Solution:
So, you first need to revoke the token. Then save refresh tokens in long-term storage and continue to use them as long as they remain valid.
As you are using refresh token, then you need to change the http post request https://accounts.google.com/o/oauth2/token to https://www.googleapis.com/oauth2/v4/token
So your code will be look like below:
String refreshToken = "1/ljll6d9ME3Uc13jMrBweqXugV4g4timYcXXXXXXXXX";
HttpPost request = new HttpPost("https://www.googleapis.com/oauth2/v4/token");
List<NameValuePair> params = new ArrayList<NameValuePair>();
...............
...............
Revoking procedure:
There are 2 ways for revoking.
A user can revoke access by visiting Account Settings
It is also possible for an application to programmatically revoke the access given to it.
To programmatically revoke a token, your application makes a request to https://accounts.google.com/o/oauth2/revoke and includes the token as a parameter:
curl https://accounts.google.com/o/oauth2/revoke?token={token}
The token can be an access token or a refresh token. If the token is an access token and it has a corresponding refresh token, the refresh token will also be revoked.
N.B: If the revocation is successfully processed, then the status code
of the response is 200. For error conditions, a status code 400 is
returned along with an error code.
Resource Link:
Offline access, Using refresh token and Revoke a token
This happened to me when I was testing with Static Responses, i.e. using reserved product IDs for testing (like android.test.purchased). SkyWalker's solution did not help in this case.
Then I used real product IDs, published my app as alpha to google play and side-loaded the release apk into my device and now everything works as expected.
Be sure to read carefully chapter Setting Up for Test Purchases in google docs to prepare your app and account properly for testing.
Check out this to see API request and response. Need help with the API Explorer
API: https://www.googleapis.com/androidpublisher/v1.1/applications/packageName/subscriptions/subscriptionId/purchases/token
Request parameters:
packageName:PACKAGE_NAME
subscriptionId:SUBSCRIPTION_ID
token:PURCHASE_TOKEN

How to include OAuth headers into async fetch request?

I would like to use asynchronous requests in my google engine application to trigger google app script (which is deployed as web app) :
URLFetchService fetcher = URLFetchServiceFactory.getURLFetchService();
Future future = fetcher.fetchAsync(req);
HTTPResponse response = (HTTPResponse) future.get();
but fetchAsync method accepts only urls or com.google.appengine.api.urlfetch.HTTPRequest
which does not offer much more options : https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/urlfetch/HTTPRequest
I do not see way how to add OAuth security headers into asynchrounous fetch service. We build authorized requests by using standart HttpRequest method.
Sample HttpRequest with included OAuth :
HttpRequest contactrequest = rf.buildGetRequest(shortenEndpoint);
GoogleHeaders headers = new GoogleHeaders();
headers.setContentType("application/x-www-form-urlencoded");
headers.setAuthorization("OAuth " + creds.getAccessToken());
contactrequest.setHeaders(headers);
contactrequest.getHeaders().set("GData-Version", "3.0");
Is there a way how to send async OAuth authorized requests ?
Answer : OAuth headers cannot be specified in fetchAsync service. Alternative is use queque tasks.
Now new question come up : how to pass 'user context' when you invoking google app script programatically : Invoking Google App script programatically and user identity? ?

Oauth problems with Scribe

I'm using scribe for making an app that has oauth support. I didn't found problems With Twitter, but when using facebook I have problems...
This is the code that works on twitter oauth
OAuthService s = /* ... Facebook oauth init ... */
final Token requestToken = s.getRequestToken();
final String authURL = s.getAuthorizationUrl(requestToken);
It gives me an error at the second line:
12-20 10:01:31.475: E/AndroidRuntime(5405): java.lang.UnsupportedOperationException: Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there
12-20 10:01:31.475: E/AndroidRuntime(5405): at org.scribe.oauth.OAuth20ServiceImpl.getRequestToken(OAuth20ServiceImpl.java:45)
I know that it says that I might use getAuthorizationUrl... But I have to pass a requestToken...
Could you please help me?
It would be helpful any example with Scribe and Facebook
Thanks!
PS: Same problem with Windows Live ! =(
EDIT:
I have been looking at the source code of the Scribe library and I found something
https://github.com/fernandezpablo85/scribe-java/blob/master/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java
Here we can see that I can call the getAuthorizationUrl(...) with null parameter because it doesn't use it.... But I think the prioblem now is that the config isn't filled...
here is how I initialize facebook service:
new ServiceBuilder()
.provider(FacebookApi.class)
.apiKey(....)
.apiSecret(....)
.scope("email,offline_access")
.callback("oauth://facebook")
.build();
Is this correct?
Thanks!
private static final Token EMPTY_TOKEN = null;
OAuthService service = new ServiceBuilder()
.provider(FacebookApi.class)
.apiKey(apiKey)
.apiSecret(apiSecret)
.callback("http://www.example.com/oauth_callback/")
.build();
String authorizationUrl = service.getAuthorizationUrl(EMPTY_TOKEN);
All you now need to redirect user to this URL and let him verify them self to get code from facebok.
There are a good amount of example with very good documentation for almost all major Oath
system
here is for Facebook
FacebookExample
For all major providers
Scribe Example Directory
Edit
After looking at the discussion my suggestion is to get a full understanding about Oauth1 and Oauth2.
You've got it all wrong. OAuth 2 Protocol never returns a request token like OAuth 1.
Oauth 1 does an HTTP POST request and returns an unauthorized request token. Then, you will have to authorize your unauthorized token to receive an authorized token (That's 2 HTTP call).
Oauth 2, on the other hand, doesn't have a request token flow, you will need to do an HTTP GET for an authorization token (1 HTTP call only). Hence why Scribe says that you need to call getAuthorizedUrl.
See this Facebook Example, to see how to retrieve an authorized token using OAuth 2.

Categories