9

I need to make a connection with Viagogo website using oAuth. Referring to their documentation I need to create a request similar to the following one

Using the example in step 1A, this means you may generate a signature base string that looks like the following:

GET&http%3A%2F%2Fapi.viagogo.net%2FPublic%2FSimpleOAuthAccessRequest&oauth_consumer_key%3Dtestkey%26oauth_nonce%3Dmyn0nc3%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1292404912%26oauth_version%3D1.0%26scope%3DAPI.Public

I am using the following code but when I comment lines 1,2 it return unauthorized error, and when I use them it shows oauthService.signRequest returns void.

TradeKingAPI.java

import org.scribe.builder.api.DefaultApi10a;
import org.scribe.model.Token;

public class TradeKingAPI extends DefaultApi10a {
    @Override
    public String getRequestTokenEndpoint() {
        return "http://api.viagogo.net/Public/SimpleOAuthAccessRequest";
    }
    @Override
    public String getAccessTokenEndpoint() {
        return "http://api.viagogo.net/Public/SimpleOAuthAccessRequest";
    }
    @Override
    public String getAuthorizationUrl(Token requestToken) {
        return "http://api.viagogo.net/Public/SimpleOAuthAccessRequest";
    }
}

main.java

import org.scribe.builder.ServiceBuilder;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.oauth.OAuthService;

import api.TradeKingAPI;
import org.scribe.builder.api.DefaultApi10a;
import org.scribe.model.OAuthConstants;
import org.scribe.oauth.OAuthService;

   ........

    OAuthService oauthService = new ServiceBuilder()
            .provider(TradeKingAPI.class)
            .apiKey("My consumer key")
            .apiSecret("My secret")
            .scope("API.Public")
            .build();

    Long seconds = (System.currentTimeMillis() / 1000);
    System.out.println(">>>" + seconds);
    String stSeconds = seconds.toString();
    OAuthRequest request = new OAuthRequest(Verb.GET, "http://api.viagogo.net/Public
                                                                     /SimpleOAuthAccessRequest");

    request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, "My consumer key");
    request.addOAuthParameter(OAuthConstants.NONCE, "myn0nc3");
    request.addOAuthParameter(OAuthConstants.SIGN_METHOD, "HMAC-SHA1");
    request.addOAuthParameter(OAuthConstants.TIMESTAMP, seconds.toString());
    request.addOAuthParameter(OAuthConstants.VERSION, "1.0");
    request.addOAuthParameter("scope", "API.Public");

 1  String signature = oauthService.signRequest(OAuthConstants.EMPTY_TOKEN, request);

 2  request.addOAuthParameter(OAuthConstants.SIGNATURE,signature);
    Response response = request.send();
    System.err.println(">>" + response.isSuccessful());
    System.err.println(">>" + response.getMessage());
    System.err.println(">>" + response.getBody());
J888
  • 1,944
  • 8
  • 42
  • 76
  • 2
    have you searched around and maybe found [Similar questions](http://stackoverflow.com/questions/5674130/how-to-get-an-oauth-request-token-for-google-using-java?rq=1) – Mgetz Jul 18 '13 at 14:11
  • 2
    Why not use existing Java OAuth libraries? – Buhake Sindi Jul 18 '13 at 14:14
  • @BuhakeSindi I could not find any, would you give me an example ? or point me to a tutorial please thanks. – J888 Jul 18 '13 at 23:01
  • @Mgetz have tcame across that one before, but prefer to do it automatically that answer requires many lines of codes. – J888 Jul 18 '13 at 23:03
  • @JackRamzi, there are few, like [Scribe](https://github.com/fernandezpablo85/scribe-java) or [JOAuth](http://code.google.com/p/joauth/), to name a few. – Buhake Sindi Jul 19 '13 at 09:31
  • @BuhakeSindi I am using scribe in my question! – J888 Jul 20 '13 at 04:53

2 Answers2

9

From what I understand from Viagogo public API access documentation, the token you get in the step 1, is the equivalent to a request token in a complete OAuth 1.0a "dance".

So, you should be able to use scribe-java internal classes to get this token without doing it by hand. The only difference is that in scribe, this request sends also a callback url to the OAuth server for the next step of OAuth "dance".

As I can't get a consumer account I can only make assumption here. So let's have 2 scenarios :

Scenario 1 : Viagogo server tolerate extra parameter (i.e. call back URL)

so you can go with this code

import org.scribe.builder.api.DefaultApi10a;
import org.scribe.model.Token;

public class TradeKingAPI extends DefaultApi10a {

    @Override
    public Verb getRequestTokenVerb()
    {
      return Verb.GET;
    }

    @Override
    public String getRequestTokenEndpoint() {
        return "http://api.viagogo.net/Public/SimpleOAuthAccessRequest";
    }

    @Override
    public String getAccessTokenEndpoint() {
        return "none";
    }

    @Override
    public String getAuthorizationUrl(Token requestToken) {
        return "none";
    }
}

Then your calling code will be :

OAuthService service = new ServiceBuilder()
                            .provider(TradeKingAPI.class)
                            .signatureType(QueryString)
                            .apiKey("My consumer key")
                            .apiSecret("My secret")
                            .scope("API.Public")
                            .build();

Token requestToken = service.getRequestToken();

//make your API calls

OAuthRequest request = new OAuthRequest(Verb.GET,
                       "http://api.viagogo.net/Public/Event/235");
service.signRequest(requestToken, request);
Response response = request.send();
System.out.println(response.getBody());

But as I said, if Viagogo security is a bit strict and it refuses the useless param oauth_callback, you'll need to switch to scenario 2

Scenario 2 : Build your own OAuthService

In this scenario you have to create a new OAuthService to avoid dealing with OAuthCallback parameter.

import org.scribe.builder.api.DefaultApi10a;
import org.scribe.model.*;
import org.scribe.oauth.OAuth10aServiceImpl;

import java.util.Map;

public class OAuth10aServiceForViagogo extends OAuth10aServiceImpl {

    private OAuthConfig config;
    private DefaultApi10a api;

    public OAuth10aServiceForViagogo(DefaultApi10a api, OAuthConfig config) {
        super(api, config);

        this.api = api;
        this.config = config;
    }

    private void addOAuthParams(OAuthRequest request, Token token) {
        request.addOAuthParameter(OAuthConstants.TIMESTAMP, api.getTimestampService().getTimestampInSeconds());
        request.addOAuthParameter(OAuthConstants.NONCE, api.getTimestampService().getNonce());
        request.addOAuthParameter(OAuthConstants.CONSUMER_KEY, config.getApiKey());
        request.addOAuthParameter(OAuthConstants.SIGN_METHOD, api.getSignatureService().getSignatureMethod());
        request.addOAuthParameter(OAuthConstants.VERSION, getVersion());
        request.addOAuthParameter(OAuthConstants.SCOPE, config.getScope());
        request.addOAuthParameter(OAuthConstants.SIGNATURE, getSignature(request, token));

    }

    private String getSignature(OAuthRequest request, Token token) {

        String baseString = api.getBaseStringExtractor().extract(request);
        String signature = api.getSignatureService().getSignature(baseString, config.getApiSecret(), token.getSecret());

        return signature;
    }

    private void appendSignature(OAuthRequest request) {
        for (Map.Entry<String, String> entry : request.getOauthParameters().entrySet()) {
            request.addQuerystringParameter(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public Token getRequestToken(RequestTuner tuner) {
        OAuthRequest request = new OAuthRequest(api.getRequestTokenVerb(), api.getRequestTokenEndpoint());

        addOAuthParams(request, OAuthConstants.EMPTY_TOKEN);
        appendSignature(request);

        Response response = request.send(tuner);
        String body = response.getBody();

        return api.getRequestTokenExtractor().extract(body);
    }
}

TrakingApi class will be slightly different to create the an OAuth10aServiceForViagogo when calling createService :

import org.scribe.builder.api.DefaultApi10a;
import org.scribe.model.Token;

public class TradeKingAPI extends DefaultApi10a {

    @override
    public OAuthService createService(OAuthConfig config)
    {
      return new OAuth10aServiceForViagogo(this, config);
    }

    @Override
    public Verb getRequestTokenVerb()
    {
      return Verb.GET;
    }

    @Override
    public String getRequestTokenEndpoint() {
        return "http://api.viagogo.net/Public/SimpleOAuthAccessRequest";
    }

    @Override
    public String getAccessTokenEndpoint() {
        return "none";
    }

    @Override
    public String getAuthorizationUrl(Token requestToken) {
        return "none";
    }
}

Then your calling code will be the same :

    OAuthService service = new ServiceBuilder()
                                .provider(TradeKingAPI.class)
                                .signatureType(QueryString)
                                .apiKey("My consumer key")
                                .apiSecret("My secret")
                                .scope("API.Public")
                                .build();

    Token requestToken = service.getRequestToken();

    //make your API calls

    OAuthRequest request = new OAuthRequest(Verb.GET,
                           "http://api.viagogo.net/Public/Event/235");
    service.signRequest(requestToken, request);
    Response response = request.send();
    System.out.println(response.getBody());

I didn't test all this code because I can't access consumer and secret key, but it should be close to what you need.

Antoine Sabot-Durand
  • 4,875
  • 17
  • 33
  • I used both methods but run into same errors, I am also wondering where you are retrieving those variables such as config.getApiKey() –  Jul 25 '13 at 12:17
  • As I said without a consumer key it's very hard to help you, because it's like testing in the dark : each Social media has it's little twist you can only see when testing for real. If you have a way to obtain me a key, I can give a try... – Antoine Sabot-Durand Jul 25 '13 at 12:41
  • `config` is an `OauthConfig` object. It is an internal class used by Scribe `ServiceBuilder`, it is instantiated when you call `build()`: http://bit.ly/166IUnq – Antoine Sabot-Durand Jul 25 '13 at 12:50
  • I have noticed while I was using your code, I missed the .signatureType(QueryString) when I added it the IDE shows an error that it does not recognise it –  Jul 25 '13 at 21:38
  • It's an enum: `org.scribe.model.SignatureType.QueryString` try to replace `SignatureType` by `SignatureType.QueryString` your IDE should find it. – Antoine Sabot-Durand Jul 26 '13 at 08:37
  • Hmm @J888, perhaps you could give a feedback on my answer to your question. Accept it or award the bounty before end if grace period or tell what's wrong with it. Thx – Antoine Sabot-Durand Jul 28 '13 at 14:07
  • Sorry for the delay I am still investigating the issue – J888 Jul 29 '13 at 02:54
  • @AntoineSabot-Durand I’ve tried the code as well it does not work I used System.out.println(request.send().isSuccessful()); which returns false –  Jul 29 '13 at 10:59
  • @MirMoorido Again, I cannot help further without an application key for Viagogo to perform tests. As they don't answer when you asked one to their support (ask last week), the only solution if you want more help would be to send me your application key by mail : asd [at] redhat [dot] com. – Antoine Sabot-Durand Jul 29 '13 at 11:39
  • @AntoineSabot-Durand I'm trying to do the similar authentication with Netsuite API but we are given only 'AuthorizationURL' and not 'RequestTokenEndpoint'. Am wondering if `RequestTokenEndpoint` is mandatory or can we authenticate just using 'AuthorizationURL' ? – OTUser Jan 21 '19 at 17:00
3

I'm assuming you're trying to get the access token (e.g you're calling SimpleOAuthAccessRequest). Scribe's OauthService has methods to handle this.

BUT ... if you're going to do it manually, here is what's wrong with your code - at least with what you've listed here. I'm assuming you've configured scribe correctly.

  • don't pass the consumer secret with your request, that is only for signing the request
  • you should use addOauthParameter vs addQueryStringParameter
  • you should use the Scribe constants
  • you need to sign the request (again, Scribe's OauthService has help method for signing request)

Here's your updated snippet of code.

UPDATE: Have Scribe provide all the Oauth parameters for you

OAuthRequest request = new OAuthRequest(Verb.GET, ...
//since you're just passing Oauth parameters and nothing else, 
//you can use signRequest will create Oauth Parameters for you
service.signRequest(OAuthConstants.EMPTY_TOKEN, request)
Response response = request.send()
ikumen
  • 11,275
  • 4
  • 41
  • 41
  • Thanks for your answer, actually I prefer to do it automatically but could not find a tutorial to learn it. Regarding scribe configuration I will update the code. – J888 Jul 18 '13 at 23:00
  • not sure if you've seen, but the scribe [git page has examples](https://github.com/fernandezpablo85/scribe-java/tree/master/src/test/java/org/scribe/examples) on how to use the OauthService to retrieve the access token: – ikumen Jul 18 '13 at 23:17
  • yes I tried to use different parts of those codes to assemble it :D – J888 Jul 18 '13 at 23:41
  • Thanks for your answer, It shows an error message on oauthService.signRequest line, question is updated. – J888 Jul 21 '13 at 00:13
  • Sorry, I took a look at the code I gave you and realize it was totally wrong (I mixed up what I have on my project with what you're doing). Basically since you're just sending a request to the endpoint with only Oauth parameters you can have Scribe create and sign the Oauth parameters w/ `signRequest` method. Earlier I mixed up the signRequest with what should have been `getSignature` – ikumen Jul 21 '13 at 15:17