Getting 401 when requesting access token with signpost within android - android

Here is my code, i keep getting an exception "Authorization failed (server replied with a 401). This can happen if the consumer key was not correct or the signatures did not match." on this line 'provider.retrieveAccessToken(consumer, verifier);'. I have triple checked my consumer key and secret and my twitter application is set as a Browser and tried setting provider.setOAuth10a(true), i have been struggling on this for 2 days!! I am using signpost 1.2.1.1 (core & commonshttp4), If anyone can help! Please im desperate
private static final String CONSUMER_KEY = "MY_CONSUMER_KEY";
private static final String CONSUMER_SECRET = "MY_CONSUMER_SECRET";
private static final String CALLBACK_URL = "tweet-mapper://mainactivity";
private static final String REQUEST_URL = "https://api.twitter.com/oauth/request_token";
private static final String ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
private static final String AUTH_URL = "https://api.twitter.com/oauth/authorize";
private static final String PREFERENCE_FILE = "twitter_oauth.prefs";
private static CommonsHttpOAuthConsumer consumer;
private static CommonsHttpOAuthProvider provider;
private static String ACCESS_KEY;
private static String ACCESS_SECRET;
private Twitter twitter;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
loginViaOAuth();
}
private void loginViaOAuth() {
try {
consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
provider.setOAuth10a(true);
provider = new CommonsHttpOAuthProvider(REQUEST_URL, ACCESS_TOKEN_URL, AUTH_URL);
String authURL = provider.retrieveRequestToken(consumer, CALLBACK_URL);
this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authURL)));
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
#Override
protected void onResume() {
super.onResume();
Uri uri = this.getIntent().getData();
if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {
String verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);
Log.d("verifier:", verifier);
try {
provider.setOAuth10a(true);
provider.retrieveAccessToken(consumer, verifier);
ACCESS_KEY = consumer.getToken();
ACCESS_SECRET = consumer.getTokenSecret();
AccessToken a = new AccessToken(ACCESS_KEY, ACCESS_SECRET);
// initialize Twitter4J
twitter = new Twitter();
twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
twitter.setOAuthAccessToken(a);
String tweet = "#OAuth working via android app!";
twitter.updateStatus(tweet);
Toast.makeText(this, tweet, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}

Just found out a possible solution: You need to set a Callback URL on your twitter application account.

I had exactly the same problem on my Android application. It was even more frustrating that my twitter login was perfectly working and starting to fail on the signature for some random reasons.
I ran a lot of tests and I found that the problem came from the Android browser which is used in the OAuth process:
if you are logging in using the stored login/password, or if you have a cookie with your Twitter session and just have to click on "Accept", it fill fail with the 401 error
if you manually delete and re-enter your password, then it works!
I still can't understand how this affects the API call, but I guess there is some mix up in the browser when you submit the "accept" form with pre-entered information.
I'd be very curious to see if my workaround solves also your problem. I understand this is not a proper solution, but this is a beginning.
EDIT: use http:// instead of https:// for the Twitter OAuth URLs and it solves the problem. I still don't unsertand what is happening...

Check your api request it must be .json or .xml, something like
https://api.jabbakam.com/network/get_list.json or
http://api.twitter.com/1/account/verify_credentials.xml
I advise you to use Scribe library there is a built in class for using Twitter API.
https://github.com/fernandezpablo85/scribe-java/blob/master/src/test/java/org/scribe/examples/TwitterExample.java
When you create your twitter keys did you make Access level: Read and write?

Related

Android: Display public Twitter timeline using OAuth and Twitter4J

So I'm trying to get a list of status objects from a public Twitter timeline ( not my own Twitter timeline or anything that I have admin access to, just a public one from a local organization ) using the Twitter4J library in Android Studio, but I'm getting a little confused by the documentation. I'm running into this error: "Invalid access token format."
I did create a developers account with Twitter and got a consumer key and token, as well as an access token and secret numbers. Those values are saved in a set of private static strings for now. TWITTER_ZOO_ID is a private long with the Twitter ID number for the feed that I want to display. Here's the applicable code that I currently have:
Twitter twitter;
List<Status> statuses = null;
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey( TWITTER_CONSUMER_KEY )
.setOAuthConsumerSecret( TWITTER_CONSUMER_SECRET )
.setOAuthAccessToken( TWITTER_AUTH_TOKEN )
.setOAuthAccessTokenSecret( TWITTER_AUTH_TOKEN_SECRET );
try {
TwitterFactory tf = new TwitterFactory(cb.build());
twitter = tf.getInstance();
twitter.setOAuthConsumer( TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET );
statuses = twitter.getUserTimeline( TWITTER_ZOO_ID );
}
catch( TwitterException e ) {
Log.e( "TwitterListFragment", "Twitter Exception" );
return;
}
for( Status status : statuses )
mAdapter.add( status );
If anyone has a link to a good example for Twitter 1.1 using Twitter4J, or can provide an example of how to get those statuses, I'd really appreciate it. I'm currently using Android Studio and including Twitter4J in Gradle from MavenCentral.
Thank you!
EDIT:
Upon further reading, I've added this additional code without success:
twitter.setOAuthConsumer( TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET );
AccessToken token = new AccessToken( TWITTER_AUTH_TOKEN, TWITTER_AUTH_TOKEN_SECRET );
twitter.setOAuthAccessToken( token );
If you want to get info from a public Twitter timeline, you can use Application-only Authentication, because the user doesn´t need to login, I think it fits you because you don´t use admin rights.
The application-only auth flow follows these steps:
An application encodes its consumer key and secret into a specially
encoded set of credentials.
An application makes a request to the POST
oauth2/token endpoint to exchange these credentials for a bearer token.
When accessing the REST API, the application uses the bearer token to authenticate.
Because twitter4j has added this feature recently, you should use the last snapshot library.
An example using it:
private ConfigurationBuilder builder;
private Twitter twitter;
private TwitterFactory factory;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.init_act_layout);
// setup
builder = new ConfigurationBuilder();
builder.setUseSSL(true);
builder.setApplicationOnlyAuthEnabled(true);
builder.setOAuthConsumerKey(Constants.CONSUMER_KEY);
builder.setOAuthConsumerSecret(Constants.CONSUMER_SECRET);
Configuration configuration = builder.build();
factory = new TwitterFactory(configuration);
((MyApp) (MyApp.getApp())).setTFactory(factory);
if (isNeededTwitterAuth()) {
twitter = factory.getInstance();
//Get the token async and save it
}
//Search tweets
}
/*
* Checks if twitter access token is already saved in preferences
*
* #return true if auth needed
*/
private boolean isNeededTwitterAuth() {
SharedPreferences settings = getSharedPreferences(Constants.TWITTER_PREFERENCES, Context.MODE_PRIVATE);
String twitterAccesToken = settings.getString("bearerAccessToken", "");
String twitterTokenType = settings.getString("bearerTokenType", "");
return ((twitterAccesToken.length() == 0) && (twitterTokenType.length() == 0));
}
}
To get the bearer token, do it out of Main UI thread to avoid Network exception, f.i. using AsyncTask:
#Override
protected OAuth2Token doInBackground(Void... params) {
OAuth2Token bearerToken = null;
try {
bearerToken = twitter.getOAuth2Token();
} catch (TwitterException e) {
e.printStackTrace();
}
return bearerToken;
}
When you obtain the bearer token, save it:
SharedPreferences appSettings = getSharedPreferences(Constants.TWITTER_PREFERENCES, MODE_PRIVATE);
SharedPreferences.Editor prefEditor = appSettings.edit();
prefEditor.putString("bearerAccessToken", result.getAccessToken());
prefEditor.putString("bearerTokenType", result.getTokenType());
prefEditor.commit();
And to use the bearer token:
OAuth2Token bearerToken = new OAuth2Token(bearerTokenType, bearerAccesstoken);
twitter.setOAuth2Token(bearerToken);
And search tweets (always out of Main thread):
#Override
protected QueryResult doInBackground(Void... params) {
twitter.setOAuth2Token(bearerToken);
Query query = new Query();
[...]
result = twitter.search(query);
A complete explanation in the blog (in Spanish...)
And a complete example in the twitter4j github
Hope it helps!
I would recommend using the recently updated Twitter SDK (Fabric).
https://docs.fabric.io/android/twitter/twitter.html

How can I provide multiple-user access using Google+ accounts on the Android app

I'm working on a multi-user Android application that provides to its users access to GMaps (find one another), chat and so on. Users should login to application using their accounts on Twitter, Facebook, Google+ etc. Everything works fine with all accounts except G+ - application can get access to G+ API only with its owner account. With other accounts I receive com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found or "authorization error". App is registered on the API Console, and OAuth2.0 authentication used. I use standard authentication mechanism from Google sites. Is it possible to use different G+ accounts to login?
Here is my code (Android v1.6):
public class GooglePlusActivity extends Activity {
public static final String LOG_TAG = GooglePlusActivity.class.getSimpleName();
public static final String EXTRA_FIRSTNAME = "firstname";
public static final String EXTRA_LASTNAME = "lastname";
public static final String EXTRA_NICKNAME = "nickname";
public static final String EXTRA_SEX = "sex";
public static final String EXTRA_AVATAR = "avatar";
public static final String EXTRA_ID_SOCNET = "id_socnet";
private ApplicationSettings mSettings;
private Person mProfile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSettings = ((TomskApplication)getApplication()).getSettings();
signIn();
}
private void signIn() {
WebView webView = new WebView(this);
setContentView(webView);
webView.getSettings().setJavaScriptEnabled(false);
String googleAuthorizationRequestUrl = new GoogleAuthorizationRequestUrl(
mSettings.getGPID(), mSettings.getGPRedirectURI(),
mSettings.getGPScope()).build();
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
if (url.startsWith(mSettings.getGPRedirectURI())) {
try {
Intent res_intent = new Intent();
if (url.indexOf("code=") != -1) {
String code = url.substring(mSettings
.getGPRedirectURI().length() + 7, url
.length());
AccessTokenResponse token = new GoogleAuthorizationCodeGrant(
new NetHttpTransport(),
new JacksonFactory(), mSettings.getGPID(),
mSettings.getGPSecret(), code, mSettings
.getGPRedirectURI()).execute();
mSettings.setGPToken(token);
// Loading user data
retrieveProfile();
if (mProfile == null) {retrieveProfile();}
res_intent.putExtra(EXTRA_FIRSTNAME, mProfile
.getName().getGivenName());
res_intent.putExtra(EXTRA_LASTNAME, mProfile
.getName().getFamilyName());
res_intent.putExtra(EXTRA_NICKNAME,
mProfile.getNickname());
res_intent.putExtra(EXTRA_SEX, mProfile.getGender());
res_intent.putExtra(EXTRA_AVATAR, mProfile
.getImage().getUrl());
res_intent.putExtra(EXTRA_ID_SOCNET, mProfile.getId());
setResult(Activity.RESULT_OK, res_intent);
view.setVisibility(View.INVISIBLE);
finish();
} else if (url.indexOf("error=") != -1) {
view.setVisibility(View.INVISIBLE);
setResult(Activity.RESULT_CANCELED);
finish();
}
} catch (IOException e) {
Log.d(LOG_TAG, e.toString());
}
return true;
} else {
return false;
}
}
});
webView.loadUrl(googleAuthorizationRequestUrl);
}
/**
* Retrieve user profile
*/
private void retrieveProfile() throws IOException {
JsonFactory jsonFactory = new JacksonFactory();
HttpTransport transport = new NetHttpTransport();
AccessTokenResponse token = mSettings.getGPToken();
GoogleAccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(
token.accessToken, transport, jsonFactory,
mSettings.getGPID(), mSettings.getGPSecret(),
token.refreshToken);
Builder b = Plus.builder(transport, jsonFactory)
.setApplicationName("MyApp/1.0");
b.setHttpRequestInitializer(accessProtectedResource);
Plus plus = b.build();
mProfile = plus.people().get("me").execute();
}
}
I've searched on Google sites, Stack Overflow but found nothing. Please help.
Dont know that this will help but, if you are desperate....
New release of some of the Android client side libs on 4/4/2012 here
and there is fresh Google+ sample, using some reconfigured classes in the main() method where they access protected resources. The new version in R 1.8 is different than your code , at least at the top of the stack.... IMO the use in the new example of the Credential class and of the PLUS.Builder is probably going to boil down to pretty much the same implementation that you already have. You may want to look at the newer sample if you cannot get anything else to work.
new code from googlePlus sample in 1.8
public static void main(String[] args) {
try {
try {
// authorization
Credential credential = OAuth2Native.authorize(
HTTP_TRANSPORT, JSON_FACTORY, new LocalServerReceiver(),
Arrays.asList(PlusScopes.PLUS_ME));
// set up global Plus instance
plus = Plus.builder(HTTP_TRANSPORT, JSON_FACTORY)
.setApplicationName("Google-PlusSample/1.0").setHttpRequestInitializer(credential)
.build();
older code here

Verify Twitter app is logged in on Android

My app I'm developing launches the official twitter app new post screen so the user can post a tweet with some extra text added in the intent. I have got this working nicely however things get a little confused if the user is not logged in with the twitter app. The app launches but the user has to sign in, once they've done that the normal twitter screen appears, if they use the back button to get back to my app the new post screen actually appears after hitting back on the twitter feed screen.
Is there any way I can check that a user is actually signed into the twitter app before trying to run the intent?
I think it's a Twitter app internal issue and you can't test for it.
On the other hand you could provide a Dialog warning the user for this matter with a "Do not show this dialog anymore" checkbox so he gets advised and can dimiss forever the Dialog. You could even provide instructions to authenticate insside the Twitter app in this Dialog.
I am using twitter4j lib.
Here I check for the username. If the username is null then there is no user signed in , else I get the username. This user name is available in the access token which I store in shared preference.
username= mySession.getUsername();
username = (username.equals("")) ? "Not logged in" : username;
code for mySession :-
public class MySession {
private SharedPreferences sharedPref;
private Editor editor;
private static final String TWEET_AUTH_KEY = "auth_key";
private static final String TWEET_AUTH_SECRET_KEY = "auth_secret_key";
private static final String TWEET_USER_NAME = "user_name";
private static final String SHARED = "Twitter_Preferences";
public TwitterSession(Context context) {
sharedPref = context.getSharedPreferences(SHARED, Context.MODE_PRIVATE);
editor = sharedPref.edit();
}
public void storeAccessToken(AccessToken accessToken, String username) {
editor.putString(TWEET_AUTH_KEY, accessToken.getToken());
editor.putString(TWEET_AUTH_SECRET_KEY, accessToken.getTokenSecret());
editor.putString(TWEET_USER_NAME, username);
editor.commit();
}
public void resetAccessToken() {
editor.putString(TWEET_AUTH_KEY, null);
editor.putString(TWEET_AUTH_SECRET_KEY, null);
editor.putString(TWEET_USER_NAME, null);
editor.commit();
}
public String getUsername() {
return sharedPref.getString(TWEET_USER_NAME, "");
}
public AccessToken getAccessToken() {
String token = sharedPref.getString(TWEET_AUTH_KEY, null);
String tokenSecret = sharedPref.getString(TWEET_AUTH_SECRET_KEY, null);
if (token != null && tokenSecret != null)
return new AccessToken(token, tokenSecret);
else
return null;
}
}
Hope this will help you.
Try this function which will in turn returns you true or false.
True : Logged in
False : Not logged in
twitter.getAuthorization() function will throw you an error if it is not logged in by handling this you can find whether user is previously logged in or not.
public static boolean isAuthenticated(SharedPreferences prefs) {
String token = prefs.getString(OAuth.OAUTH_TOKEN, "");
String secret = prefs.getString(OAuth.OAUTH_TOKEN_SECRET, "");
AccessToken a = new AccessToken(token,secret);
Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
try {
twitter.getAuthorization();
return true;
} catch (Exception e) {
return false;
}
}
just add these lines in the oncreate() in ur activity
final Session activeSession = Twitter.getInstance().core.getSessionManager().getActiveSession();
if (activeSession != null){
//do someting
}

Does the following OAuth process to authorise users still supported by twitter?

I want to make an android app which will update status in twitter.
I am using signpost-core-1.2.1.1 and signpost-commonshttp4-1.2.1.1 jar files.I have given internet uses permission and i have registered app in twitter giving read,write and direct messages permission. Also filled up the callback Url.But retrieveRequestToken() function throws OAuthCommunicationException.
code snippet:
private static final String CALLBACK_URI = "app://twitter";
private static final String REQUEST_TOKEN_URL = "https://api.twitter.com/oauth/request_token";
private static final String ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
private static final String AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize";
String CONSUMER_KEY = "I4bwezijxf6VwpU8x0tygg";
String CONSUMER_SECRET = "Y6vSdZs3zWBrNogXZWSHKZ590RSXqB5wBwj8vFaayk";
private static CommonsHttpOAuthConsumer consumer;
private static CommonsHttpOAuthProvider provider;
consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
provider = new DefaultOAuthProvider(REQUEST_TOKEN_URL,ACCESS_TOKEN_URL, AUTHORIZE_URL);
String authUrl="";
authUrl = provider.retrieveRequestToken(consumer,CALLBACK_URI);
I am totally stuck with this.Please reply.
Your consumer credentials are working fine in my test twitter app, so could not find the issue with you.
Here is the complete detailed article on Twitter integration and you can literally copy the code of TwitterConnectWebActivity in your app and call it by an intent for twitter integration.Twitter integration in Android app complete codeThis must solve your problem.

retrieveRequestToken(CommonsHttpOAuthConsumer,CALLBACK_URI) functions throws OAuthCommunicationException

I want to make an android app which will update status in twitter.
I am using signpost-core-1.2.1.1 and signpost-commonshttp4-1.2.1.1 jar files.I have given internet uses permission and i have registered app in twitter giving read,write and direct messages permission. Also filled up the callback Url.
code snippet:
private static final String CALLBACK_URI = "app://twitter";
private static final String REQUEST_TOKEN_URL = "https://api.twitter.com/oauth/request_token";
private static final String ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
private static final String AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize";
String CONSUMER_KEY = "XXXXXXXXXX";
String CONSUMER_SECRET = "XXXXXXXXXX";
private static CommonsHttpOAuthConsumer consumer;
private static CommonsHttpOAuthProvider provider;
consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
provider = new DefaultOAuthProvider(REQUEST_TOKEN_URL,ACCESS_TOKEN_URL, AUTHORIZE_URL);
String authUrl="";
authUrl = provider.retrieveRequestToken(consumer,CALLBACK_URI);
I am totally stuck with this.Please reply.
Signpost documentation says DefaultOAuthProvider has some problem with Android implementation of java.net. They suggest use of CommonsHttpOAuthProvider instead. I was having the same problem. This solved this exception in my case. Hope this helps.
First By android application we are not allowed to send callbackurl, so use "oob" instead of callbackurl, and there is an api for twitter which is also supported on android, it is jTwitter.

Categories

Resources