3
votes

I'm following https://dev.twitter.com/web/sign-in/implementing to implement OAuth signup in my application with twitter.

Here is the service which presents the User the authorize this app dialog from twitter:

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/twitter")
public Response redirectToTwitter() {
    Configuration cfg = new ConfigurationBuilder().setOAuthConsumerKey(TWITTER_CONSUMER_KEY)
                                                  .setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET)
                                                  .build();
    Twitter twitter = new TwitterFactory(cfg).getInstance();
    String callbackURL = "https://localhost:9090/app/ui/oauth/twitter";
    try {
        RequestToken requestToken = twitter.getOAuthRequestToken(callbackURL);
        String authURL = requestToken.getAuthenticationURL();
        return Response.seeOther(URI.create(authURL)).build();
    } catch (TwitterException e) {
        LOG.error(e.getMessage(), e);
        return ErrorResponse.create(e.getMessage());
    }
}

This works and redirects the browser to the Twitter Page which asks for authorization. When I click Sign In the redirect dialog appears which redirect me to a URL something like:

https://localhost:9090/app/ui/oauth/twitter?oauth_token=6oWQxQAAAAAAgyORAAABTtmVVFM&oauth_verifier=GMX5SiqnkFfUu2MgirTDJnkJmtHZXn5H

@GET
@Path("/twitter")
public SocialSignInView login(@QueryParam("oauth_token") String token,
                              @QueryParam("oauth_verifier") String verifier) {
    Configuration cfg = new ConfigurationBuilder().setOAuthConsumerKey(TWITTER_CONSUMER_KEY)
            .setOAuthConsumerSecret(TWITTER_CONSUMER_SECRET)
            .setOAuthAccessToken(token)
            .build();
    Twitter twitter = new TwitterFactory(cfg).getInstance();
    String callbackURL = "https://localhost:9090/app/ui/oauth/twitter";
    String screenName = null;
    try {
        RequestToken requestToken = twitter.getOAuthRequestToken(callbackURL);
        AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, verifier);
        screenName = accessToken.getScreenName();
    } catch (TwitterException e) {
        LOG.error(e.getMessage(), e);
    }

    return new SocialSignInView(screenName);
}

At this point I have all the required parameters - according to https://dev.twitter.com/web/sign-in/implementing 3. - to retrieve an access token, however, I don't know how to put together a RequestToken object form the existing oauth_token.

With the code above I'm receiving the following error:

ERROR 13:33:06.478 [dw-165 - GET /app/ui/oauth/twitter?oauth_token=6oWQxQAAAAAAgyORAAABTtmVVFM&oauth_verifier=GMX5SiqnkFfUu2MgirTDJnkJmtHZXn5H] r.d.d.resources.SocialSignInCompleteResource: 401:Authentication credentials (https://dev.twitter.com/pages/auth) were missing or incorrect. Ensure that you have set valid consumer key/secret, access token/secret, and the system clock is in sync.
Error processing your OAuth request: Invalid oauth_verifier parameter
3
Are you able to solve this issue? I am getting the same problem.vbjain
No, I implemented this with scribe but the process should be somewhat similar in twitter4j (it was back then). I also blogged about it: akoskm.github.io/2015/07/31/twitter-sign-in-for-web-apps.html.Akos K

3 Answers

1
votes

You need to set oauth_verifier in the header when you are requesting https://api.twitter.com/oauth/access_token. These oauth_verifier you are getting as get parameters. So just set oauth_verifier=params[:oauth_verifier] in header.

0
votes

I also had this problem with twitter4j.

I had been following the this tutorial (full code here).

However, the code wasn't brilliantly written, so I made a few changes and ended up breaking things which resulted in the "Error processing your OAuth request: Invalid oauth_verifier parameter" error.

Basically, the problem/solution lay with how I got the oauth request token from twitter4j.

Paying attention to the getRequestToken() method, this is the right way to implement it:

import android.util.Log;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;

public final class TwitterUtil {

    private final static String TAG = TwitterUtil.class.getSimpleName();

    static TwitterUtil instance = new TwitterUtil();

    public static TwitterUtil getInstance() {
        return instance;
    }

    private TwitterFactory twitterFactory;
    private Twitter twitter;
    private RequestToken requestToken = null;

    private TwitterUtil() {

        ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
        configurationBuilder.setOAuthConsumerKey(Constants.TWITTER_CONSUMER_KEY);
        configurationBuilder.setOAuthConsumerSecret(Constants.TWITTER_CONSUMER_SECRET);
        Configuration configuration = configurationBuilder.build();
        twitterFactory = new TwitterFactory(configuration);
        twitter = twitterFactory.getInstance();
    }

    TwitterFactory getTwitterFactory() {

        return twitterFactory;
    }

    void setTwitterFactory(AccessToken accessToken) {

        twitter = twitterFactory.getInstance(accessToken);
    }

    public Twitter getTwitter() {

        return twitter;
    }

    RequestToken getRequestToken() {

        if (requestToken == null) {

            try {
                requestToken = twitterFactory.getInstance().getOAuthRequestToken(Constants.TWITTER_CALLBACK_URL);
            }
            catch (TwitterException e) {
                Log.e(TAG, "Could not get Twitter OAuth Request Token", e);
            }
        }
        return requestToken;
    }

    public void reset() {

        instance = new TwitterUtil();
    }
}

And this is the wrong way to implement it:

public final class TwitterUtil_WRONG {

    private final static String TAG = TwitterUtil_WRONG.class.getSimpleName();

    static TwitterUtil_WRONG instance = new TwitterUtil_WRONG();

    public static TwitterUtil_WRONG getInstance() {
        return instance;
    }

    private TwitterFactory twitterFactory;
    private Twitter twitter;

    private TwitterUtil_WRONG() {
        ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
        configurationBuilder.setOAuthConsumerKey(Constants.TWITTER_CONSUMER_KEY);
        configurationBuilder.setOAuthConsumerSecret(Constants.TWITTER_CONSUMER_SECRET);
        Configuration configuration = configurationBuilder.build();
        twitterFactory = new TwitterFactory(configuration);
        twitter = twitterFactory.getInstance();
    }

    TwitterFactory getTwitterFactory() {
        return twitterFactory;
    }

    void setTwitterFactory(AccessToken accessToken) {
        twitter = twitterFactory.getInstance(accessToken);
    }

    public Twitter getTwitter()
    {
        return twitter;
    }

    RequestToken getRequestToken() {

        try {
            return twitterFactory.getInstance().getOAuthRequestToken(Constants.TWITTER_CALLBACK_URL);
        }
        catch (Exception e) {
            Log.e(TAG, "Could not get Twitter OAuth Request Token", e);
            return null;
        }
    }

    public void reset() {
        instance = new TwitterUtil_WRONG();
    }
}
-1
votes

I had the same issue and fixed it by passing the oauth_verifier in the twitter.getOAuthAccessToken() when requesting for the AccessToken.