0

I'm trying to use Java SignPost to get Oauth support from discogs

If I call this method it provides a url to a website, then if I login I get a verification code, so far so good.

    public static String requestDiscogsAuthorization() throws Exception
    {

        OAuthConsumer consumer = new DefaultOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
        OAuthProvider provider = new DefaultOAuthProvider(
                "http://api.discogs.com/oauth/request_token",
                "http://api.discogs.com/oauth/access_token",
                "http://www.discogs.com/oauth/authorize");
        provider.setRequestHeader("User-Agent", SongKong.USER_AGENT);
        return provider.retrieveRequestToken(consumer,  OAuth.OUT_OF_BAND);
    }

I store this verification code in my application and can retrieve as UserPreferences.getInstance().getDiscogsAuthorization(). So now I want to sign a url I try and call the getAccessToken() below to get an access code from my verification key but I get

oauth.signpost.exception.OAuthExpectationFailedException: Authorized request token or token secret not set. Did you retrieve an authorized request token before?
    at oauth.signpost.AbstractOAuthProvider.retrieveAccessToken(AbstractOAuthProvider.java:89)
    at com.jthink.songkong.analyse.toplevelanalyzer.DiscogsAuth.getAccessToken(DiscogsAuth.java:54)

I dont see what im doing wrong

 public class DiscogsAuth
{
    /**
     * Constructs a consumer with valid access token for signing urls (can only be used once user has authorizaed application and auth code
     * available to application somewhere
     *
     * NOTE:Not thread safe, has to be done once for each thread
     *
     * @return
     * @throws Exception
     */
    public static OAuthConsumer getAccessToken() throws Exception
    {
        OAuthConsumer consumer = new DefaultOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
        OAuthProvider provider = new DefaultOAuthProvider(
                "http://api.discogs.com/oauth/request_token",
                "http://api.discogs.com/oauth/access_token",
                "http://www.discogs.com/oauth/authorize");
        provider.setRequestHeader("User-Agent", SongKong.USER_AGENT);
        provider.retrieveAccessToken(consumer, UserPreferences.getInstance().getDiscogsAuthorization());
        return consumer;
    }

    /**
     * Sign Url Connection
     *
     * @param urlConnection
     * @param consumer
     * @throws Exception
     */
    public static void signUrl(HttpURLConnection urlConnection, OAuthConsumer consumer) throws Exception
    {
         consumer.sign(urlConnection);
    }
}
Steve Bennett
  • 114,604
  • 39
  • 168
  • 219
Paul Taylor
  • 13,411
  • 42
  • 184
  • 351

3 Answers3

0

Probably your method call not able to get the verification code when you try to call provider.retrieveAccessToken ,you can try by printing the verification code before you pass it on to the provider.retrieveAccessToken method.

0

You are missing access token and access token secret.

To sign an OAuth 1.0 request you need three things: the CONSUMER_SECRET that you already have, the access token and the access token secret which you will get in the oauth_token and oauth_token_secret variables respectively in the response of the Temporary Credentials request.

I have no experience with Java, but according to Signpost documentation i guess that you should call this...

consumer.setTokenWithSecret(ACCESS_TOKEN, TOKEN_SECRET);

...before you try to sign the url

consumer.sign(urlConnection);

Seems like you can get ACCESS_TOKEN and TOKEN_SECRET with ...

String accessToken = provider.getResponseParameter('oauth_token');
String tokenSecret = provider.getResponseParameter('oauth_token_secret');

... after you call this:

provider.retrieveAccessToken(consumer, verificationCode);

Here is my take (I didn't try it):

 public class DiscogsAuth
{
    /**
     * Constructs a consumer with valid access token for signing urls (can only be used once user has authorizaed application and auth code
     * available to application somewhere
     *
     * NOTE:Not thread safe, has to be done once for each thread
     *
     * @return
     * @throws Exception
     */
    public static OAuthConsumer getAccessToken() throws Exception
    {
        OAuthConsumer consumer = new DefaultOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
        OAuthProvider provider = new DefaultOAuthProvider(
                "http://api.discogs.com/oauth/request_token",
                "http://api.discogs.com/oauth/access_token",
                "http://www.discogs.com/oauth/authorize");
        provider.setRequestHeader("User-Agent", SongKong.USER_AGENT);
        provider.retrieveAccessToken(consumer, UserPreferences.getInstance().getDiscogsAuthorization());
        
        // Retrieve access token and access token secret
        String accessToken = provider.getResponseParameter('oauth_token');
        String tokenSecret = provider.getResponseParameter('oauth_token_secret');
        
        // Set them on the consumer so it can sign the requestst with them
        consumer.setTokenWithSecret(accessToken, tokenSecret);

        return consumer;
    }

    /**
     * Sign Url Connection
     *
     * @param urlConnection
     * @param consumer
     * @throws Exception
     */
    public static void signUrl(HttpURLConnection urlConnection, OAuthConsumer consumer) throws Exception
    {
         consumer.sign(urlConnection);
    }
}
Community
  • 1
  • 1
Peter Hudec
  • 2,462
  • 3
  • 22
  • 29
  • But if you look at my getAccessToken() method I do provider.retrieveAccessToken(consumer,UserPreferences.getInstance().getDiscogsAuthorization()); comsumer is constructed with the CONSMER_KEY and UserPreferences.getInstance().getDiscogsAuthorization() is the verification code so I think I am doing what you suggest already – Paul Taylor Apr 07 '14 at 20:40
  • you are not calling `consumer.setTokenWithSecret()`. The consumer needs to know `ACCESS_TOKEN` and `TOKEN_SECRET` to sign the request. The question is how do you get the two values. The `provider.retrieveAccessToken()` makes a HTTP request and `ACCESS_TOKEN` and `TOKEN_SECRET` will be in the response of that request in the `oauth_token` and `oauth_token_secret` querystring parameters. Seems likely that you could get the response querystring parameters with `provider.getResponseParameter('oauth_token')` and `provider.getResponseParameter('oauth_token_secret')`. – Peter Hudec Apr 08 '14 at 13:06
  • Here is it in the docs: http://mttkay.github.io/signpost/signpost-core-apidocs/oauth/signpost/AbstractOAuthProvider.html#getResponseParameter(java.lang.String) – Peter Hudec Apr 08 '14 at 13:07
  • I updated the answer with modified version of your code. I didn't try it though, I'm not a Java guy – Peter Hudec Apr 08 '14 at 13:21
  • The problem was that I was not using the same instance of OAuthConsumer and OAuthProvider for every step. – Paul Taylor May 08 '14 at 08:27
0

The problem was that I was not using the same instance of OAuthConsumer and OAuthProvider for every step.

Paul Taylor
  • 13,411
  • 42
  • 184
  • 351