Has anyone ever successfully sent a tweet via jTwitter on Android?
I am stuck with the Authentification. I can successfully redirect the user to twitter, authorize my app and redirect to my app with new OAuthSignpostClient(CONSUMER_KEY, CONSUMER_SECRET, CALLBACK_URL). Then I store the oauth_token and oauth_verifier which are given with the Callback URL and try to use the OAuthSignpostClient again to update a state:
OAuthSignpostClient client = new OAuthSignpostClient(TwitterOAuthActivity.CONSUMER_KEY, TwitterOAuthActivity.CONSUMER_SECRET, accessToken, accessTokenSecret);
// Ready to go!
Twitter twitter = new Twitter(null, client);
CharSequence date = DateFormat.format("dd.MM.yyyy # hh:mm:ss", new Date());
twitter.updateStatus("Yay. It works! " + date);
Which ends in a TwitterException without a caused by:
05-11 12:24:32.643: E/AndroidRuntime(25897): winterwell.jtwitter.TwitterException$E401: Could not authenticate with OAuth.
05-11 12:24:32.643: E/AndroidRuntime(25897): http://api.twitter.com/1/statuses/update.json (anonymous)
05-11 12:24:32.643: E/AndroidRuntime(25897): at winterwell.jtwitter.URLConnectionHttpClient.processError(URLConnectionHttpClient.java:425)
05-11 12:24:32.643: E/AndroidRuntime(25897): at winterwell.jtwitter.OAuthSignpostClient.post2_connect(OAuthSignpostClient.java:345)
Does anyone has an idea where my Problem is?
The verifier from the callback url is a temporary key. It let's you unlock the OAuthSignpostClient object that you have. You can't use it to construct a new OAuthSignpostClient.
You need to call:
client.setAuthorizationCode(verifier);
// The client can now be used!
// To use it again, without the oauth dance, store _these_ tokens:
String[] tokens = client.getAccessToken();
You may also want to check out the new AndroidTwitterLogin class which makes things easy:
AndroidTwitterLogin atl = new AndroidTwitterLogin(myApp,
MY_TWITTER_KEY,MY_TWITTER_SECRET,MY_TWITTER_CALLBACK) {
protected void onSuccess(Twitter jtwitter, String[] tokens) {
jtwitter.setStatus("I can now post to Twitter!");
// Recommended: store tokens in your app for future use
// with the constructor OAuthSignpostClient(String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret)
}
};
atl.run();
Related
I was creating the sample to get all the google calendar events and show the events with details on list. But it always throws the exception while fetching the data.
I tried to get events by follow the below link
https://www.c-sharpcorner.com/article/get-and-create-google-calendar-events-from-net/
and i also refer the google link also
https://developers.google.com/api-client-library/dotnet/get_started#simple
The issue was raised on make a request and i tried with both API key and client service.
I created the calendar credential by
GoogleCredential credential;
using(var stream = new FileStream(keyfilepath, FileMode.Open, FileAccess.Read)) {
credential = GoogleCredential.FromStream(stream)
.CreateScoped(Scopes).CreateWithUser("demo123#gmail.com");
}
var service = new CalendarService(new BaseClientService.Initializer() {
HttpClientInitializer = credential,
ApplicationName = "Calendar Sample",
});
EventsResource.ListRequest request = service.Events.List("primary");
Events events = request.Execute(); /// Makes crash
Android Crash : System.Net.WebException: 'Unable to resolve host "oauth2.googleapis.com": No address associated with hostname'
Windows : Google.Apis.Auth.OAuth2.Responses.TokenResponseException: 'Error:"unauthorized_client", Description:"Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.", Uri:""'
Suggest me to resolve the problem.
I've got InvalidAccessTokenException at any attempt to upload file to Dropbox.
For authorization I use next algorithm:
Auth.startOAuth2Authentication(context, APP_KEY);
//granting access
//previous activity is reopened
String accessToken = Auth.getOAuth2Token();
DbxRequestConfig requestConfig = DbxRequestConfig.newBuilder(CLIENT_ID)
.withHttpRequestor(OkHttp3Requestor.INSTANCE)
.build();
DbxClientV2 client = new DbxClientV2(requestConfig, accessToken);
client.files().uploadBuilder(ADDRESS_IN_DROPBOX)
.uploadAndFinish(inputStream);
which returns InvalidAccessTokenException.
Maybe I'm doing something wrong.
Also maybe Auth.getOAuth2Token() return auth code instead of access code (which is a bit obvious from method name), but how to get access code when auth code is known?
PS I've used Android project as example - https://github.com/dropbox/dropbox-sdk-java/tree/master/examples/android and performed auth exactly as in example.
EDIT-----------------------------------------------------------------------------------------------
Problem occurs ONLY after revoking access to the app from account settings at Dropbox webpage.
You noted:
Problem occurs ONLY after revoking access to the app from account settings at Dropbox webpage.
In that case, this InvalidAccessTokenException is expected. If a user revokes the token, e.g., by unlinking the app via https://www.dropbox.com/account/security , any further API calls attempted with that token will fail with this exception. You should have your code catch this exception and prompt the user to re-link the app if they want to continue using it.
I found problem in my code.
I've used DropboxClientFactory like in example from Dropbox where client init looks like this
public static void init(String accessToken) {
if (sDbxClient == null)) {
DbxRequestConfig requestConfig = DbxRequestConfig.newBuilder("ID")
.withHttpRequestor(OkHttp3Requestor.INSTANCE)
.build();
sDbxClient = new DbxClientV2(requestConfig, accessToken);
}
}
And when access token was revoked - init process was not called because sDbxClient is already initialized.
So I added variable accessCode to DropboxClientFactory to hold used access token and now init looks like this
public static void init(String accessToken) {
if (sDbxClient == null || !accessToken.equals(accessCode)) {
DbxRequestConfig requestConfig = DbxRequestConfig.newBuilder("ID")
.withHttpRequestor(OkHttp3Requestor.INSTANCE)
.build();
sDbxClient = new DbxClientV2(requestConfig, accessToken);
}
}
Intermittently, GoogleTokenResponse.parseIdToken() has an NullPointerExpection because the token response does not contain an ID token. Without changing any code, sometimes there is an ID token, and sometimes there isn't. Note that GoogleTokenResponse.getAccessToken() always works.
With no change to any code whatsoever, the ID token will be missing from one minute to the next, even if the access token is always available.
How can I debug this? Where to look?
I get the server auth code using this in an Android client using Google Play Games API:
PendingResult<Games.GetServerAuthCodeResult> pendingResult =
Games.getGamesServerAuthCode(mGoogleApiClient, Constants.web_client_ID);
pendingResult.setResultCallback(new ResultCallback<Games.GetServerAuthCodeResult>() {
#Override
public void onResult(Games.GetServerAuthCodeResult getTokenResult) {
sendToServer(getTokenResult.getCode());
}
});
On the server side (Google Cloud Endpoints), I exchange the code for a token using this code:
try {
tokenResponse = new GoogleAuthorizationCodeTokenRequest(
transport,mJFactory,
"https://www.googleapis.com/oauth2/v4/token",
web_client_ID,web_client_secret,
authCode,
"")
.execute();
} ...
String accessToken = tokenResponse.getAccessToken();
GoogleIdToken idToken = null;
try {
idToken = tokenResponse.parseIdToken(); //-- FAILES HERE INTERMITTENTLY!!!!
} ...
Since it seems that Play Games Services does not guarantee an ID token using Games.getGamesServerAuthCode one should follow the directions in this post and get the ID token as it recommends:
Once you have the access token, you can now call
www.googleapis.com/games/v1/applications//verify/ using that
access token. Pass the auth token in a header as follows:
“Authorization: OAuth ” The response value will contain
the player ID for the user.
See this for a full example.
I need to send info to the google endpoint, which then sets up object with Sendgrid and then sends the email. The emails are not working, nothing is sent through from the app engine.
Part of my endpoint code:
#ApiMethod(name = "sendEmail")
public sendEmailObject sendEmail(#Named("sendTo") String sendTo, #Named("sentFromClient") String sentFromClient, #Named("sendDescription") String sendDescription) {
SendGrid sendgrid = new SendGrid(..., ...);
SendGrid.Email email = new SendGrid.Email();
email.addTo(..);
email.addToName(..);
email.setReplyTo(..);
email.setSubject(..);
email.setText(..);
email.setFrom(...);
sendEmailObject emailoObject = new sendEmailObject();
try {
SendGrid.Response response = sendgrid.send(email);
emailoObject.setSendMailSucccess(response.getMessage().toString());
} catch (SendGridException e) {
e.printStackTrace();
emailoObject.setSendMailSucccess(e.toString());
}
Is there something I need to set on the app engine? Like opening a port or some other settings? Sendgrid seems to use port 5252, but have no idea where to allow that port, or if its automatically done?
I also used a different email when registering for Sendgrid, than App engine, could this cause a problem?
The problem was that when creating an Sendgrid object I used username and password. When I changed that to the key generated on sendgrid it worked!!!
SendGrid sendgrid = new SendGrid("key");
I'm trying to access a Purchase Status API from my ASP.NET web server using Google APIs .NET Client Library which is a recommended way for using Purchase API v1.1. However, the Authorization page of this API suggests direct web requests to Google's OAuth2 pages instead of using the corresponding client libraries.
OK, I tried both methods with all variations I could imagine and both of them lead to "The remote server returned an error: (400) Bad Request.".
Now what I've done to get to my point. First I've made all steps 1-8 under the Creating an APIs Console project of the Authorization page. Next I generated a refresh token as described there. During refresh token generation I chose the same Google account as I used to publish my Android application (which is in published beta state now).
Next I've created a console C# application for test purposes in Visual Studio (may be console app is the problem?)
and tried to call the Purchase API using this code (found in some Google API examples):
private static void Main(string[] args)
{
var provider =
new WebServerClient(GoogleAuthenticationServer.Description)
{
ClientIdentifier = "91....751.apps.googleusercontent.com",
ClientSecret = "wRT0Kf_b....ow"
};
var auth = new OAuth2Authenticator<WebServerClient>(
provider, GetAuthorization);
var service = new AndroidPublisherService(
new BaseClientService.Initializer()
{
Authenticator = auth,
ApplicationName = APP_NAME
});
var request = service.Inapppurchases.Get(
PACKAGE_NAME, PRODUCT_ID, PURCHASE_TOKEN);
var purchaseState = request.Execute();
Console.WriteLine(JsonConvert.SerializeObject(purchaseState));
}
private static IAuthorizationState GetAuthorization(WebServerClient client)
{
IAuthorizationState state =
new AuthorizationState(
new[] {"https://www.googleapis.com/auth/androidpublisher"})
{
RefreshToken = "4/lWX1B3nU0_Ya....gAI"
};
// below is my redirect URI which I used to get a refresh token
// I tried with and without this statement
state.Callback = new Uri("https://XXXXX.com/oauth2callback/");
client.RefreshToken(state); // <-- Here we have (400) Bad request
return state;
}
Then I tried this code to get the access token (I found it here: Google Calendar API - Bad Request (400) Trying To Swap Code For Access Token):
public static string GetAccessToken()
{
var request = WebRequest.Create(
"https://accounts.google.com/o/oauth2/token");
request.Method = "POST";
var postData =
string.Format(
#"code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",
// refresh token I got from browser
// also tried with Url encoded value
// 4%2FlWX1B3nU0_Yax....gAI
"4/lWX1B3nU0_Yax....gAI",
// ClientID from Google APIs Console
"919....1.apps.googleusercontent.com",
// Client secret from Google APIs Console
"wRT0Kf_bE....w",
// redirect URI from Google APIs Console
// also tried Url encoded value
// https%3A%2F%2FXXXXX.com%2Foauth2callback%2F
"https://XXXXX.com/oauth2callback/");
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
using (var dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
}
try
{
// request.GetResponse() --> (400) Bad request again!
using (var response = request.GetResponse())
{
using (var dataStream = response.GetResponseStream())
{
using (var reader = new StreamReader(dataStream))
{
var responseFromServer = reader.ReadToEnd();
var jsonResponse = JsonConvert.DeserializeObject<OAuth2Response>(responseFromServer);
return jsonResponse.access_token;
}
}
}
}
catch (Exception ex) { var x = ex; }
return null;
}
So, to sum up all my long story:
Is it possible at all to pass OAuth2 authorization using either of methods above from a C# Console Application (without user interaction)?
I've double checked the redirect URI (since I saw a lot of discussed troubles because of it here on stackoverflow) and other parameters like ClientID and ClientSecret. What else I could do wrong in the code above?
Do I need to URL encode a slash in the refresh token (I saw that the first method using client library does it)?
What is the recommended way of achieving my final goal (Purchase API access from ASP.NET web server)?
I'll try to answer your last question. If you access your own data account, you dont need to use client id in oAuth2. Let's use service account to access Google Play API.
Create a service account in Google Developer Console > Your project > APIs and auth > Credentials > Create a new key. You will download a p12 key.
Create a C# project. You can choose console application.
Install google play api library from Google.Apis.androidpublisher. Nuget. You can find other library for dotnet in Google APIs Client Library for .NET
Link google api project with your google play account in API access
Authenticate and try to query information. I'll try with listing all inapp item. You can just change to get purchase's status
String serviceAccountEmail = "your-mail-in-developer-console#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"physical-path-to-your-key\key.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { "https://www.googleapis.com/auth/androidpublisher" }
}.FromCertificate(certificate));
var service = new AndroidPublisherService(
new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "GooglePlay API Sample",
});
// try catch this function because if you input wrong params ( wrong token) google will return error.
var request = service.Inappproducts.List("your-package-name");
var purchaseState = request.Execute();
// var request = service.Purchases.Products.Get(
//"your-package-name", "your-inapp-item-id", "purchase-token"); get purchase'status
Console.WriteLine(JsonConvert.SerializeObject(purchaseState));
You should do the following in your
private static IAuthorizationState GetAuthorization(WebServerClient client) method:
private IAuthorizationState GetAuthorization(WebServerClient client)
{
IAuthorizationState state = AuthState;
if (state != null)
{
return state;
}
state = new AuthorizationState()
{
RefreshToken = "4/lWX1B3nU0_Ya....gAI",
Callback = new Uri(#"https://XXXXX.com/oauth2callback/")
};
client.RefreshToken(state);
// Store and return the credentials.
HttpContext.Current.Session["AUTH_STATE"] = _state = state;
return state;
}
Let me know if it works for you.
Be aware that we know that the whole OAuth2 flow is awkward today, and we are working to improve it.