Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Tumblr oAuth Confusion

I'm trying to implement the Tumblr API in an Android app. I'm really getting stuck with authorizing a user so that they can do things such as post and view their dashboard. I don't really understand oAuth, and the Tumblr API documentation sort of skips right over it. I have no idea if I'm supposed to prompt the user for their credentials, or what to do with those once I have them, or anything like that. I added the Signpost library to my project, but I've been scratching my head since then. Anybody familiar with oAuth on Android who would care to fill me in? Thanks!

like image 345
Nick Avatar asked Oct 15 '11 03:10

Nick


2 Answers

Yes, the documentation is not that good. You should first read about OAuth. Twitter has a good overview.

First of all you need a consumer key and secret (you can get those by registering your app in tumblr). After that, you should use the auth URLs that Tumblr provides to get the authorization from the user. Usually you will generate a request URL, from which you can take the user to the browser where he/she will login and authorize your app. This will trigger a callback to your app, and you will be able to get the oAuth token. Save this in your app (SharedPreferences) so that you won't need to ask the user again to authenticate. With this token you will be able to interact with Tumblr's API that requires authentication.

Note that you could also implement a webview instead of making the user use the browser. Though, this requires a bit more of work.

I have found that the latest signpost library does not work well with Tumblr. You will need a bit older version. Head here and download these files:

  • signpost-core-1.2.jar
  • signpost-commonshttp4-1.2.jar (this is needed specially if you want to target pre-froyo devices)

Import both libraries to your project. To use them, basically you need to call the following code:

CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY,
         CONSUMER_SECRET);
CommonsHttpOAuthProvider provider = new CommonsHttpOAuthProvider(
         REQUEST_TOKEN_URL,
         ACCESS_TOKEN_URL,
         AUTH_URL);
String authUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL); 

CALLBACK_URL could be something like this: "tumblrapp://tumblrapp.com/ok". There is no need to set the callback URL on the Tumblr settings.

Also, you will need to set an intent filter so your app gets called after authorization. Make sure that your Manifest looks like this:

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="tumblrapp"/>
            </intent-filter>

Now after authentication you can get the token like this:

Uri uri = this.getIntent().getData();
if (uri != null) {
   String token = uri.getQueryParameter("oauth_token");
}

I made a quick sample app. You can check it out here. You might want to move the request to a background thread as it will block the UI.

like image 152
Jan S. Avatar answered Oct 09 '22 01:10

Jan S.


Just so new people coming in have an easier way to implement this, There's an Android Library on GitHub to login the user for you. It returns the Tokens so you may use them with Jumblr Library.

Edit 1:

On Recommendation of Bhargav Rao & tttony, below is an elaboration of the login process for Tumblr. Though I recommend using the library as it takes care of the messy part, for those who like getting their hands dirty...

The Tumblr Login is a 3 staged process. For info on what OAuth is, refer this simplified guide

1) Using httpOAuthprovider in the signpost library, generate a request token.

            //Generate a new oAuthConsumer object
            commonsHttpOAuthConsumer
                    = new CommonsHttpOAuthConsumer(
                    "Consumer Key",
                    "Consumer Secret Key");
            //Generate a new oAuthProvider object
            commonsHttpOAuthProvider
                    = new CommonsHttpOAuthProvider(
                    "https://www.tumblr.com/oauth/request_token",
                    "https://www.tumblr.com/oauth/access_token",
                    "https://www.tumblr.com/oauth/authorize");
            //Retrieve the URL to which the user must be sent in order to authorize the consumer
            return commonsHttpOAuthProvider.retrieveRequestToken(
                    commonsHttpOAuthConsumer,
                    "Callback URL as registered with Tumblr"
            );

2) The response of the previous return statement is a URL which the user should be redirected to for him to login to Tumblr and authorize your app. I did this in a webview for better control of app flow. Refer this for info on how to load content to WebViews. Attach a WebView client and override the shouldOverrideUrlLoading method. This will enable you to intercept URLs before they are loaded. Post Authorization, tumblr issues an OAuthVerifier which will be used to exchange for Tokens.

public boolean shouldOverrideUrlLoading(WebView view, String strUrl) {
                //Log Current loading URL
                Log.i(TAG, strUrl);
                //Check if the Currently loading URL is that of the call back URL mentioned on top
                if (strUrl.toLowerCase().contains("Callback URL".toLowerCase())) {
                    //Parse string URL to conver to URI
                    Uri uri = Uri.parse(strUrl);
                    //instantiate String variables to store OAuth & Verifier tokens
                    String strOAuthToken = "";
                    String strOAuthVerifier = "";
                    //Iterate through Parameters retrieved on the URL
                    for (String strQuery : uri.getQueryParameterNames())
                        switch (strQuery) {
                            case "oauth_token":
                                //Save OAuth Token
                                //Note : This is not the login token we require to set on JumblrToken
                                strOAuthToken = uri.getQueryParameter(strQuery);
                                break;

                            case "oauth_verifier":
                                //Save OAuthVerifier
                                strOAuthVerifier = uri.getQueryParameter(strQuery);
                                break;
                        }
                }

3) Exchange the OAuthVerifier for access tokens.

try {
        //Queries the service provider for access tokens. The method does not return anything.
        //It stores the OAuthToken & OAuthToken secret in the commonsHttpOAuthConsumer object.
        commonsHttpOAuthProvider.retrieveAccessToken(commonsHttpOAuthConsumer, strOAuthVerifier);
        //Check if tokens were received. If Yes, save them to SharedPreferences for later use.
        if(!TextUtils.isEmpty(commonsHttpOAuthConsumer.getToken())) {
            Log.i(TAG, "OAuthToken : " + commonsHttpOAuthConsumer.getToken());
        }

        if(!TextUtils.isEmpty(commonsHttpOAuthConsumer.getTokenSecret())) {    
            Log.i(TAG, "OAuthSecretToken : " + commonsHttpOAuthConsumer.getTokenSecret());
        }
    } catch (OAuthCommunicationException e) {
        e.printStackTrace();
        return null;
    } catch (OAuthExpectationFailedException e) {
        e.printStackTrace();
        return null;
    } catch (OAuthNotAuthorizedException e) {
        e.printStackTrace();
        return null;
    } catch (OAuthMessageSignerException e) {
        e.printStackTrace();
        return null;
    }

4) Once Token and TokenSecret are retrieved, use them with Jumblr to continue using TumblrAPIs.

like image 43
Clinkz Avatar answered Oct 09 '22 01:10

Clinkz