iosoauthlinkedin-apihmac

Linkedin API Error Invalid Signature in iPhone Starter Kit


I've tried to run the OAuthStarterKit xcode project out of the box, entered the correct api key/secret and oauth user token/secret. When I get to authorizing with this code:

    OAMutableURLRequest *request = 
        [[[OAMutableURLRequest alloc] initWithURL:requestTokenURL
                                         consumer: self.consumer
                                            token: self.requestToken   
                                         callback:linkedInCallbackURL
                                signatureProvider:sha] autorelease];

It returns the error "signature_invalid", which seems to indicate an incorrect signature. the clear text and secret have a mix of upper and lower case chars, I'm not sure that that should make a difference.

If I use

requestTokenURLString = @"https://api.linkedin.com/uas/oauth/requestToken?scope=r_basicprofile+r_emailaddress";

It returns invalid sig... but if I use a basic permissions call

requestTokenURLString = @"https://api.linkedin.com/uas/oauth/requestToken;

It works fine, but it means I only have basic profile permissions, where I need things like the email address.

Entering all of the same data in the test console seems to work fine here:

https://developer.linkedin.com/oauth-test-console

Anyone know what I should be doing, thinking, or where I should be looking? Further log info:

oauth_problem=signature_invalid
oauth_problem_advice=com.linkedin.security.auth.pub.LoginDeniedInvalidAuthTokenException while obtaining request token for: POST https://api.linkedin.com/uas/oauth/requestToken/oauth_callback:hdlinked://linkedin/oauth 
oauth_consumer_key: XXX
oauth_nonce
oauth_signature_method: 3DHMACSHA1

2012-09-04 23:36:07.054 OAuthStarterKit[31952:c07] secret: TIDi9XXXXXXX
2012-09-04 23:36:07.054 OAuthStarterKit[31952:c07] base64EncodedResult: JXW6ZWUpXv7ba98o2hcUXodDhmg=

I'm using the code sample from here https://github.com/synedra/LinkedIn-OAuth-Sample-Client

Edit: Will be trying to get to the bottom of this tomorrow and answer my own question if no one beats me to it.


Solution

  • After much wrangling with the Linkedin API Beast, I found the issue to be in the way things are encoded, a long story, in OAuthLoginView.m in method 'requestTokenFromProvider' I needed to include the param 'scope' with the relevant permissions in a OARequestParameter object.

    (based off the github repo -> https://github.com/synedra/LinkedIn-OAuth-Sample-Client)

    After that, wherever you're making your api call, (in OAuthStarterKit for example) like in ProfileTabView::profileApiCall you can fire off URL posts like this: http://api.linkedin.com/v1/people/~:(id,first-name,last-name,industry)"]; or if you need their email address, it appears (as long as you've got permission to access email, you can grab that too as simply as this:

    NSURL *url = [NSURL URLWithString:@"http://api.linkedin.com/v1/people/~:(id,first-name,last-name,industry,email-address)"];
    

    See the code for using a OARequestParameter in the URL request below...

    - (void)requestTokenFromProvider
    {
        OAMutableURLRequest *request = 
                [[[OAMutableURLRequest alloc] initWithURL:requestTokenURL
                                                 consumer:self.consumer
                                                    token:nil   
                                                 callback:linkedInCallbackURL
                                        signatureProvider:nil] autorelease];
    
        [request setHTTPMethod:@"POST"];
    
        OARequestParameter * scopeParameter=[OARequestParameter requestParameter:@"scope" value:@"r_fullprofile r_contactinfo r_emailaddress"];
    
        [request setParameters:[NSArray arrayWithObject:scopeParameter]];
    
        OADataFetcher *fetcher = [[[OADataFetcher alloc] init] autorelease];
        [fetcher fetchDataWithRequest:request
                             delegate:self
                    didFinishSelector:@selector(requestTokenResult:didFinish:)
                      didFailSelector:@selector(requestTokenResult:didFail:)];    
    }
    

    And for a more in depth short cut to using linkedin's API I'll keep some quicktips on my blog here ->http://techrantnz.blogspot.com.au/2012/09/the-linkedin-api-with-oauthstarterkit.html

    If you wish to check things are working, check the method which is called if it succeeds

    - (void)profileApiCallResult:(OAServiceTicket *)ticket didFinish:(NSData *)data
    

    If you output the response body you might see something like:

    2012-09-05 21:40:55.109 OAuthStarterKit[12244:c07] profile: {
        emailAddress = "[my email]@gmail.com";
        firstName = Dave;
        id = XXXXXX;
        industry = "Information Technology and Services";
        lastName = "XXXXXXXX";
    }