views:

322

answers:

3

I've been struggling with this one for a few days now. I've got a test app set up to connect to LinkedIn via OAuth. I want to be able to update a user's status, but at the moment I'm unable to interact with LinkedIn's API at all.

I am able to successfully get a requestToken, then an accessToken, but when I issue a request to the API, I see an 'unauthorized' error that looks something like this:

object(OAuthException)#2 (8) { 
 ["message:protected"]=>  string(73) "Invalid auth/bad request (got a 401, expected HTTP/1.1 20X or a redirect)" 
 ["string:private"]=>  string(0) "" 
 ["code:protected"]=>  int(401) 
 ["file:protected"]=>  string(47) "/home/pmfeorg/public_html/dev/test/linkedin.php" 
 ["line:protected"]=>  int(48) 
 ["trace:private"]=>  array(1) { 
  [0]=>  array(6) { 
   ["file"]=>  string(47) "/home/pmfeorg/public_html/dev/test/linkedin.php" 
   ["line"]=>  int(48) 
   ["function"]=>  string(5) "fetch" 
   ["class"]=>  string(5) "OAuth" 
   ["type"]=>  string(2) "->" 
   ["args"]=>  array(2) { 
    [0]=>  string(35) "http://api.linkedin.com/v1/people/~" 
    [1]=>  string(3) "GET" 
   } 
  } 
 } 
 ["lastResponse"]=>  string(358) "  401  1276375790558  0000  [unauthorized]. OAU:Bhgk3fB4cs9t4oatSdv538tD2X68-1OTCBg-KKL3pFBnGgOEhJZhFOf1n9KtHMMy|48032b2d-bc8c-4744-bb84-4eab53578c11|*01|*01:1276375790:xmc3lWhXJvLSUZh4dxMtrf55VVQ= " 
 ["debugInfo"]=>  array(5) { 
 ["sbs"]=>  string(329) "GET&http%3A%2F%2Fapi.linkedin.com%2Fv1%2Fpeople%2F~&oauth_consumer_key%3DBhgk3fB4cs9t4oatSdv538tD2X68-1OTCBg-KKL3pFBnGgOEhJZhFOf1n9KtHMMy%26oauth_nonce%3D7068001084c13f2ee6a2117.22312548%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1276375790%26oauth_token%3D48032b2d-bc8c-4744-bb84-4eab53578c11%26oauth_version%3D1.0" 
 ["headers_sent"]=>  string(401) "GET /v1/people/~?GET&oauth_consumer_key=Bhgk3fB4cs9t4oatSdv538tD2X68-1OTCBg-KKL3pFBnGgOEhJZhFOf1n9KtHMMy&oauth_signature_method=HMAC-SHA1&oauth_nonce=7068001084c13f2ee6a2117.22312548&oauth_timestamp=1276375790&oauth_version=1.0&oauth_token=48032b2d-bc8c-4744-bb84-4eab53578c11&oauth_signature=xmc3lWhXJvLSUZh4dxMtrf55VVQ%3D HTTP/1.1 User-Agent: PECL-OAuth/1.0-dev Host: api.linkedin.com Accept: */*" 
 ["headers_recv"]=>  string(148) "HTTP/1.1 401 Unauthorized Server: Apache-Coyote/1.1 Date: Sat, 12 Jun 2010 20:49:50 GMT Content-Type: text/xml;charset=UTF-8 Content-Length: 358" 
 ["body_recv"]=>  string(358) "  401  1276375790558  0000  [unauthorized]. OAU:Bhgk3fB4cs9t4oatSdv538tD2X68-1OTCBg-KKL3pFBnGgOEhJZhFOf1n9KtHMMy|48032b2d-bc8c-4744-bb84-4eab53578c11|*01|*01:1276375790:xmc3lWhXJvLSUZh4dxMtrf55VVQ= " 
 ["info"]=>  string(216) "About to connect() to api.linkedin.com port 80 (#0) Trying 64.74.98.83... connected Connected to api.linkedin.com (64.74.98.83) port 80 (#0) Connection #0 to host api.linkedin.com left intact Closing connection #0 " 
 }
} 

My code looks like this (based on the FireEagle example from php.net):

$req_url = 'https://api.linkedin.com/uas/oauth/requestToken';
$authurl = 'https://www.linkedin.com/uas/oauth/authenticate';
$acc_url = 'https://api.linkedin.com/uas/oauth/accessToken';
$api_url = 'http://api.linkedin.com/v1/people/~';
$callback = 'http://www.pmfe.org/dev/test/linkedin.php';
$conskey = 'Bhgk3fB4cs9t4oatSdv538tD2X68-1OTCBg-KKL3pFBnGgOEhJZhFOf1n9KtHMMy';
$conssec = '####################SECRET KEY#####################';

session_start();

try {
  $oauth = new OAuth($conskey,$conssec,OAUTH_SIG_METHOD_HMACSHA1,OAUTH_AUTH_TYPE_URI);
  $oauth->enableDebug();

  if(!isset($_GET['oauth_token'])) {
    $request_token_info = $oauth->getRequestToken($req_url);
    $_SESSION['secret'] = $request_token_info['oauth_token_secret'];
    header('Location: '.$authurl.'?oauth_token='.$request_token_info['oauth_token']);
    exit;
  } else {
    $oauth->setToken($_GET['oauth_token'],$_SESSION['secret']);
    $access_token_info = $oauth->getAccessToken($acc_url);
    $_SESSION['token'] = $access_token_info['oauth_token'];
    $_SESSION['secret'] = $access_token_info['oauth_token_secret'];
  } 
    $oauth->setToken($_SESSION['token'],$_SESSION['secret']);
 $oauth->fetch($api_url, OAUTH_HTTP_METHOD_GET);

 $response = $oauth->getLastResponse();
} catch(OAuthException $E) {
  var_dump($E);
}

I've successfully set up a connection to Twitter and one to Facebook using OAuth, but LinkedIn keeps eluding me. If anyone could offer some advice or point me in the right direction, I will be extremely appreciative!

A: 

Unless LinkedIn has a totally wonky view of HTTP status codes, 401 means it was expecting a WWW-Authenticate header (ie: username/password in base64 format) and didn't get it, so it's denying access.

Perhaps you have to do an OAuth::setAuthType().

Marc B
A: 

Well, I found the source of the problem, but there's a new problem now:

My original question was wrong - I wasn't getting an accessToken at all. The problem was that I wasn't passing the verifier code (obtained during the requestToken step) during the getAccessToken call.

So rather than this...

$access_token_info = $oauth->getAccessToken($acc_url);

...I needed to do this...

$_SESSION['verifier'] = $_GET['oauth_verifier'];
$access_token_info = $oauth->getAccessToken($acc_url, $_SESSION['verifier'], $_SESSION['verifier']);

I hope this info helps someone else out. This is the first time I've worked with OAuth, but it seems like LinkedIn has a very strict implementation.

Anyway, now I need to figure out why LI is returning a 401 when I try to update my status... I've authorized the app, and can pull data down, but am unable to set any data. Maybe there are additional permissions hidden in LI's settings somewhere?

Jim Greenleaf
LinkedIn sends a reason for the 401 in the body of the response. What does it say?
Paul Lindner
Same response as before: Invalid auth/bad request (got a 401, expected HTTP/1.1 20X or a redirect)
Jim Greenleaf
A: 

What's the port number for connecting to LinkedIn OAuth? My company has firewall and it seems I can't connect get the access_token coming back, so I need to know the port number to have it open.

Thanks.

Alvin Chin