0

I have a Phonegap application that uses ChildBrowser to Authorize my app to connect with the users Twitter account using Oauth. Once the user signs in their Twitter account an authorize the app to connect, Twitter sends the ChildBrowser to the callback url where I retrieve the request_token from the url. But then I try to call the API to exchange the request_token for the access_token and the application does not continue past that point. It looks like the app breaks during the API call to get the access_token but I cant see how.

Any help would be greatly appreciated!!!

Thank you so much all!

Here is my javascript:

/* -- Twitter START -- */

var Twitter = {
    init:function() {

        var oauth; 
        var requestParams; 
        var options = { 
            consumerKey: 'blahblah',
            consumerSecret: 'blahblah',
            callbackUrl: "http://beaconize.com/" 
        };
        alert(localStorage.twitterKey);
        var cb = ChildBrowser.install(); // install our ChildBrowser ( cb )    
        var twitterKey = "twttrKey"; // what we will store our twitter user information in


        // our storedAccessData and Raw Data
        var storedAccessData, rawData = localStorage.getItem(twitterKey);

        // First thing we need to do is check to see if we already have the user saved!
        if(localStorage.getItem(twitterKey) !== null){

            // If we already have them
            storedAccessData = JSON.parse(rawData); // Parse our JSON object
            options.accessTokenKey = storedAccessData.accessTokenKey; // This is saved when they first sign in
            options.accessTokenSecret = storedAccessData.accessTokenSecret; // this is saved when they first sign in

            oauth = OAuth(options);
            oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true',
                function(data) {
                    var entry = JSON.parse(data.text);
                    alert("USERNAME: " + entry.screen_name);
                }
            );
        } else {

            // We don't have a user saved yet
            oauth = OAuth(options);
            oauth.get('https://api.twitter.com/oauth/request_token',
                function(data) {
                    requestParams = data.text;
                    cb.showWebPage('https://api.twitter.com/oauth/authorize?'+data.text); // This opens the Twitter authorization / sign in page     
                    cb.onLocationChange = function(loc){ Twitter.success(loc); }; // When the ChildBrowser URL changes we need to track that
                },
                function(data) { 
                    alert("ERROR: "+data);
                }
            );
        }
    },

    /*
     When The ChildBrowser URL changes we will track it here.
     We will also determine if the request was a success or not here
     */
    success:function(loc) {
        // The supplied oauth_callback_url for this session is being loaded

        /*
         We will check to see if the childBrowser's new URL matches our callBackURL
         */
        if (loc.indexOf("http://beaconize.com/?") >= 0) {

            // Parse the returned URL
            var index, verifier = '';            
            var params = loc.substr(loc.indexOf('?') + 1);

            params = params.split('&');
            for (var i = 0; i < params.length; i++) {
                var y = params[i].split('=');
                if(y[0] === 'oauth_verifier') {
                    verifier = y[1];
                }
            }


            // After the next line, nothing executes. It stops in ChildBrowser on my callback_url.


            oauth.get('https://api.twitter.com/oauth/access_token?oauth_verifier='+verifier+'&'+requestParams,
                      function(data) {               
                        var accessParams = {};
                        var qvars_tmp = data.text.split('&');
                        for (var i = 0; i < qvars_tmp.length; i++) {
                            var y = qvars_tmp[i].split('=');
                            accessParams[y[0]] = decodeURIComponent(y[1]);
                        }

                        oauth.setAccessToken([accessParams.oauth_token, accessParams.oauth_token_secret]);

                        // Save access token/key in localStorage
                        var accessData = {};
                        accessData.accessTokenKey = accessParams.oauth_token;
                        accessData.accessTokenSecret = accessParams.oauth_token_secret;

                        // SETTING OUR LOCAL STORAGE
                        alert("TWITTER: Storing token key/secret in localStorage3");
                        localStorage.setItem(twitterKey, JSON.stringify(accessData));
                      },
                      function(data) { 
                      console.log(data);

                      }
            );
                      oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true',
                                function(data) {
                                var entry = JSON.parse(data.text);
                                alert("TWITTER USER: "+entry.screen_name);

                                // FOR EXAMPLE ONLY
                                //app.init();
                                },
                                function(data) {
                                alert("ERROR: " + data); 
                                }
                                );

                      // Since everything went well we can close our childBrowser!                             
                      window.plugins.childBrowser.close();


        } else {
            // do nothing   
        }
    },
    tweet:function() {
        var storedAccessData, rawData = localStorage.getItem(twitterKey);

        storedAccessData = JSON.parse(rawData); // Parse our JSON object
        options.accessTokenKey = storedAccessData.accessTokenKey; // This is saved when they first sign in
        options.accessTokenSecret = storedAccessData.accessTokenSecret; // this is saved when they first sign in

        // jsOAuth takes care of everything for us we just need to provide the options
        oauth = OAuth(options);
        oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true',
            function(data) {
                var entry = JSON.parse(data.text);
                Twitter.post();
            }
        );
    },
    /*
     Now that we have the information we can Tweet!
     */
    post:function() {
        var theTweet = $("#tweet").val(); // Change this out for what ever you want!

        oauth.post('https://api.twitter.com/1/statuses/update.json',
            { 'status' : theTweet,  // jsOAuth encodes for us
            'trim_user' : 'true' },
            function(data) {
                var entry = JSON.parse(data.text);
                alert(entry);

                // FOR THE EXAMPLE
                app.done();
            },
            function(data) { 
                alert(data);
            }
        );      
    }
};

/* -- Twitter END -- */
Karl
  • 595
  • 1
  • 10
  • 31
  • 1
    Just to double check your callback URL in your twitter app is also http:// beaconize .com vs http:// www. beaconize .com - yeah? – Drew Dahlman May 29 '12 at 03:20
  • 1
    also have you checked to see if both verifier and requestParams have values before hitting that function? – Drew Dahlman May 29 '12 at 03:21
  • Yup both callbacks match as "http:// beaconize .com/". I'll test to see what shows up in those variables before launching the function. – Karl May 29 '12 at 04:22
  • Ok so the verifier variable id good. But if I check the value of requestParams in the init() function this is what I get oauth_token=zmdnEdTdD88...Yyug&oauth_token_secret=pOro...iE&oauth_callback_confirmed=true Which. Is what I want to see. But when I call it just before the function that calls a get to grab the access_token (in the success() function), it returns nothing. Do you think thats my problem? Should I declare that value again before that call? – Karl May 29 '12 at 04:39

2 Answers2

1

Okay so I compared your code with the original project that you are referencing. and here's where I netted out.

Looks like you are missing a couple things that are leading to this breaking.

here is the original code - this should work

oauth.get('https://api.twitter.com/oauth/access_token?oauth_verifier='+verifier+'&'+requestParams,
                      function(data) {               
                        var accessParams = {};
                        var qvars_tmp = data.text.split('&');
                        for (var i = 0; i < qvars_tmp.length; i++) {
                            var y = qvars_tmp[i].split('=');
                            accessParams[y[0]] = decodeURIComponent(y[1]);
                        }

                        oauth.setAccessToken([accessParams.oauth_token, accessParams.oauth_token_secret]);

                        // Save access token/key in localStorage
                        var accessData = {};
                        accessData.accessTokenKey = accessParams.oauth_token;
                        accessData.accessTokenSecret = accessParams.oauth_token_secret;

                        // SETTING OUR LOCAL STORAGE
                        alert("TWITTER: Storing token key/secret in localStorage3");
                        localStorage.setItem(twitterKey, JSON.stringify(accessData));
                      },
                      function(data) { 
                      console.log(data);

                      }
            );
                      oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true',
                                function(data) {
                                var entry = JSON.parse(data.text);
                                alert("TWITTER USER: "+entry.screen_name);

                                // FOR EXAMPLE ONLY
                                //app.init();
                                },
                                function(data) {
                                alert("ERROR: " + data); 
                                }
                                );

                      // Since everything went well we can close our childBrowser!                             
                      window.plugins.childBrowser.close();


        } else {
            // do nothing   
        }
    },

One thing to notice and this is where your code differs is the error function for the first oauth request - your code seems to be missing this, which isn't a huge deal - but you have taken out the formatting so those two functions are now one which is causing issues.

if you copy this code and select and paste right over your code and toggle them you will see the minor differences that are causing the issues!

Drew Dahlman
  • 4,952
  • 1
  • 22
  • 34
0

So far looking at your code, everything looks reasonable.

I notice you are doing some of the auth-dance work manually. Have you tried using the fetchRequestToken() & fetchAccessToken() methods? I wrote boiler plate code to demonstrate this.

Can you give the output of the error message? Usually It gives a clue to why Twitter didn't authorise you.

You may find this useful API reference theres also an undocumented method for parsing the url strings parseTokenRequest()

bytespider
  • 586
  • 5
  • 6
  • I haven't tried the fetchRequestToken() and fetchAccessToken() yet. But I am tempted since I can't get it to work with the manual GET calls. In your gist example you are using PIN based auth, but I would prefer avoiding using a PIN to authenticate the users. Do you have an example of the use of fetchRequestToken() and fetchAccessToken() being used for regular oauth authentication? Thanks for your help in advance! – Karl May 29 '12 at 17:46
  • The other way is to detect the change in url to the callback url, then scrape the query string for the oauth varifier. – bytespider Jun 15 '12 at 05:02
  • Libby Baldwin did a good tutorial on this http://www.mobiledevelopersolutions.com/home/start/twominutetutorials/tmt5p1 – bytespider Jun 15 '12 at 05:03