Twitter API returns invalid callback - Cannot authorize

21,006

I found I just could not get it to work this way after following the guides I've seen online.

I ended up using my own custom WebViewClient with the code:

if ( url.contains( "MY-CALLBACK:///" ) )
{
    final int start = url.indexOf( '?' ) + 1;
    final String params = url.substring( start );
    final String verifierToken = "oauth_verifier=";
    if ( params.contains( verifierToken ) )
    {
        final int value = params.indexOf( verifierToken ) + verifierToken.length();
        final String token = params.substring( value );
        view.stopLoading();                  
        authoriseNewUser( token );
    }
    else if ( params.contains( "denied" ) )
    {
        view.stopLoading();
        finish();
    }
}
else
{
    view.loadUrl( url );
}
return true;
Share:
21,006
Bojan Radivojevic Bomber
Author by

Bojan Radivojevic Bomber

Updated on July 07, 2022

Comments

  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber almost 2 years

    [SOLVED, but I'm open to new suggestions...]

    I'm integrating Twitter into my Android app using twitter4j.

    When I try to authorize with Twitter, I am calling the following endpoint with my oauth token:

    https://api.twitter.com/oauth/authenticate?oauth_token=MY_VALID_TOKEN

    which should redirect me to:

    MY-CALLBACK:///?oauth_token=***&oauth_verifier=***

    but instead, it redirects me to:

    https://api.twitter.comMY-CALLBACK///?oauth_token=***&oauth_verifier=***

    which is obviously not a valid url.
    (Also, the : is missing - it should be MY-CALLBACK:///...)

    Please note I'm using WebView for my calls


    I could manipulate this string to make everything work, but there has to be a better way...



    I am passing my callback URL to

    getOAuthRequestToken("MY-CALLBACK:///");

    and have already set the intent-filter for my activity with

    <data android:scheme="x-oauthflow-twitter" />

    Also, the activity has android:launchMode="singleInstance"



    What am I doing wrong?


    [edit:more details]

    mTwitter = new TwitterFactory().getInstance();
    mTwitter.setOAuthConsumer(Constants.TWITTER_CONSUMER_KEY, Constants.TWITTER_CONSUMER_SECRET);
    
    twitterWebView = new WebView(ActivityTwitterAuthorize.this);
    
    twitterWebView.setWebViewClient(new WebViewClient() {
    
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (url.startsWith(Constants.TWITTER_CALLBACK_URL)) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse(url));
                startActivity(intent);
    
            // HACKY PART!
            // I added the following code to force it to work, but this is a dirty hack...
            // String TWITTER_CALLBACK_INVALID_PREFIX = "https://api.twitter.comx-oauthflow-twitter///";
            // TWITTER_CALLBACK_URL = "MY-CALLBACK:///";
            // BEGIN
            } else if (url.startsWith(TWITTER_CALLBACK_INVALID_PREFIX)) {
                url = url.substring(TWITTER_CALLBACK_INVALID_PREFIX.length());
                url = Constants.TWITTER_CALLBACK_URL + url;
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse(url));
                startActivity(intent);
            // END
    
            } else {
                view.loadUrl(url);
            }
            return true;
        }
    
    });
    
    mTwitterReqToken = mTwitter.getOAuthRequestToken(Constants.TWITTER_CALLBACK_URL);
    
    twitterWebView.loadUrl(mTwitterReqToken.getAuthenticationURL());
    

    WITHOUT the hacky part, this code results in "Webpage not available" error, because the url is invalid:

    https://api.twitter.comMY-CALLBACK///?oauth_token=***&oauth_verifier=***

    If the url was MY-CALLBACK:///?oauth_token=***&oauth_verifier=*** then my activity would receive an Intent, and everything would be ok...

    WITH the "hacky part", my code works, but I would like to avoid that piece of code.

    • Dipak Keshariya
      Dipak Keshariya about 12 years
      Please Give More Details, I Don't Understand your Problem.
    • Vivek Kumar Srivastava
      Vivek Kumar Srivastava about 12 years
      you need to close webView dialog after getting if (url.startsWith(Constants.TWITTER_CALLBACK_URL)) condition.
    • Bojan Radivojevic Bomber
      Bojan Radivojevic Bomber about 12 years
      I tried that, too, but even when I type https://api.twitter.com/oauth/authenticate?oauth_token=MY_VA‌​LID_TOKEN in my browser, the Twitter api returns invalid url...
  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber about 12 years
    That's basically what I did, too (check for existence of my callback url inside the returned url, and modify it to match my expected format), but is there a better way?
  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber about 12 years
    No, that's not the point. It is perfectly ok to use just OAUTH_CALLBACK_SCHEME + ":///"
  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber about 12 years
    This is the third answer that says my callback url is wrong. No, my callback url is not wrong. I already tried this and it's the same whether I use SCHEME://HOST or just SCHEME:///
  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber about 12 years
    I tried public static final String TWITTER_CALLBACK_URL = "x-oauthflow-twitter:///"; and I also tried public static final String TWITTER_CALLBACK_URL = "x-oauthflow-twitter://callback";. Doesn't matter, it doesn't work anyway...
  • Dara Saini
    Dara Saini about 12 years
    try this dear. private static final Uri CALLBACK_URI = Uri.parse("twifj://twitterfj"); and in your custom WebViewClient if (url.startsWith(CALLBACK_URI.toString())) {}
  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber about 12 years
    Actually, I think I'll rework my code to use something like this instead of broadcasting Intents... This is far more efficient! If no one offers a better solution, I'll accept this answer.
  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber about 12 years
    I really appreciate your effort, but this doesn't help me. The url returned from server simply does NOT start with my callback uri. It starts with https://api.twitter.com and then my callback uri
  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber about 12 years
    This is definitely the best solution, I removed the intent-filter altogether! Just a suggestion for you, for extracting query parameters from your string, you could use Uri uri = Uri.parse(url); String oAuthVerifier = uri.getQueryParameter("oauth_verifier"); if (oAuthVerifier != null) {...} It looks nicer then the url.substring() thing... Thanks!
  • Bojan Radivojevic Bomber
    Bojan Radivojevic Bomber about 12 years
    I guessed that was the server-side issue. I included code for dealing with both cases, just to be on the safe side. I write to log when the "hacky" part is executed, so I will check that. I will let you know these days...
  • Afflatus
    Afflatus over 8 years
    @ScouseChris could you say you've placed this code where?
  • ScouseChris
    ScouseChris over 8 years
    @Afflatus I added that check in shouldOverrideUrlLoading