- PHP: Step-by-step OAuth for Dummies based on LinkedIn API (Part I) - Licence Fondamentale d'Informatique
vendredi 21 mars 2014

PHP: Step-by-step OAuth for Dummies based on LinkedIn API (Part I)

Part I: Redirecting User to LinkedIn

LinkedIn API is so far one of the most problematic API for developers who are trying to implement “connect” features.  The main reason is LinkedIn API is using XML for passing parameters for POST/PUT request while many standard OAuth libraries implementation are based on the more usual “query string” method.
I have tried very hard to find a good standard OAuth library for connecting to LinkedIn API, but guess what? It is so hard to find that I finally decided to dig to the basic of OAuth.  I started implementing based on LinkedIn OAuth Authentication Guide but apparently I stuck in creating a valid signature. I looked through many other guides and finally found out that LinkedIn guide actually missed out a few details. Firstly, it only mentioned about signing with consumer secret, but not with token secret.  Secondly, it didn’t really tell us what standard we should follow for url-encoding.  After struggling through many guides, I finally came out with my own step-by-step guide.
Step 1 - Get Your Consumer Key and Consumer Secret
Register your web application with LinkedIn at https://www.linkedin.com/secure/developer. You will get a Consumer Key (API Key) and a Consumer Secret code.  Lets start by this 2 lines of code:
define('LINKEDIN_KEY', 'YOUR_KEY');
define('LINKEDIN_SECRET', 'YOUR_SECRET'); 
Step 2 - Prepare The URL-Encoding Function Your Will Need
The URL encoding in OAuth follow the RFC-3896 standard. I did not really go through the standard, but the following is the function I get from most OAuth library
function urlencode_oauth($str) {
  return
    str_replace('+',' ',str_replace('%7E','~',rawurlencode($str)));
}
Step 3 - Prepare The Links
This is optional, but by keeping this organized, we can re-use the code for other web services.
$links = array(
 'request_token'=>'https://api.linkedin.com/uas/oauth/requestToken',
  'authorize'=>'https://www.linkedin.com/uas/oauth/authorize',
  'access_token'=>'https://api.linkedin.com/uas/oauth/accessToken'
);
Step 4 - Prepare OAuth Parameters
The require parameters are listed in the code. You will need to change the value of oauth_callback to your own callback URL.
$params = array(
  'oauth_callback'=>"http://www.example.com/linkedin_callback.php",
  'oauth_consumer_key'=>LINKEDIN_KEY,
  'oauth_nonce'=>sha1(microtime()),
  'oauth_signature_method'=>'HMAC-SHA1',
  'oauth_timestamp'=>time(),
  'oauth_version'=>'1.0'
);
Step 5 - Prepare The Base String
The base-string is a single line string that will be used for signing. It contains the following:
  1. The HTTP method in uppercase - GET, POST or PUT
  2. The request URL
  3. The query string sorted according to ascending order of key
These 3 items are url-encoded and combine into single line with ampersand (&) as seperator
// sort parameters according to ascending order of key
ksort($params);

// prepare URL-encoded query string
$q = array();
foreach ($params as $key=>$value) {
  $q[] = urlencode_oauth($key).'='.urlencode_oauth($value);
}
$q = implode('&',$q);

// generate the base string for signature
$parts = array(
  'POST',
  urlencode_oauth($links['request_token']),
  urlencode_oauth($q)
);
$base_string = implode('&',$parts);
Step 6 - Get The Signature
As a rule of thumb, the key for signature should be the URL-encoded Consumer Secret concatenate with token secret with ‘&’ as separator. At this stage, we don’t have any token secret, so it will be blank, but the ampersand (&) must still be there.
$key = urlencode_oauth(LINKEDIN_SECRET) . '&';
$signature = base64_encode(hash_hmac('sha1',$base_string,$key,true));
Step 7 - Put the Signature into Parameters and Prepare Authorization Header
$params['oauth_signature'] = $signature;
$str = array();
foreach ($params as $key=>$value) {
  $str[] = $key . '="'.urlencode_oauth($value).'"';
}
$str = implode(', ',$str);
$headers = array(
  'POST /uas/oauth/requestToken HTTP/1.1',
  'Host: api.linkedin.com',
  'Authorization: OAuth '.$str,
  'Content-Type: text/xml;charset=UTF-8',
  'Content-Length: 0',
  'Connection: close'
);
Step 8 - Send POST Request To LinkedIn
For this example, I use some basic functions - fsockopen(), fputs(), fgets(). You can implement this with other library like cURL.
$fp = fsockopen("ssl://api.linkedin.com",443,$errno,$errstr,30);
if (!$fp) { echo 'Unable to connect to LinkedIn'; exit(); }
$out = implode("\r\n",$headers) . "\r\n\r\n";
fputs($fp,$out);

// getting LinkedIn server response
$res = '';
while (!feof($fp)) $res .= fgets($fp,4096);
fclose($fp);
If you do everything correctly, you should get a response like this.
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain
Content-Length: 236
Date: Sun, 07 Nov 2010 03:25:59 GMT

oauth_token=cc652566-5243-835a-b12a-489224fc2bdb&oauth_token_secret=16e98de3-35ab-4508-9528-80a89d6137bc&oauth_callback_confirmed=true&xoauth_request_auth_url=https%3A%2F%2Fapi.linkedin.com%2Fuas%2Foauth%2Fauthorize&oauth_expires_in=599
Step 9 - Parse the Response to Get OAuth Token and Secret
$parts = explode("\n\n",str_replace("\r",'',$res));
$res_headers = explode("\n",$parts[0]);
if ($res_headers[0] != 'HTTP/1.1 200 OK') {
  echo 'Error getting OAuth token and secret.'; exit();
}
parse_str($parts[1],$data);
if (empty($data['oauth_token'])) {
  echo 'Failed to get LinkedIn request token.'; exit();
}
Step 10 - Save the Request Token and Secret
At this point, you should have your request token and request token secret in $data[‘oauth_token’] and $data[‘oauth_token_secret’] respectively. You need to save it as you need to use them in your callback script to get the access token in Part 2. For this example, I will save it in session.
$_SESSION['linkedin_oauth_token'] = $data['oauth_token'];
$_SESSION['linkedin_oauth_token_secret'] = $data['oauth_token_secret'];
Step 11 - Redirect your user to LinkedIn with the request token
header('Location: '.$links['authorize'].
  '?oauth_token='.urlencode($data['oauth_token']));
exit();
Your user should now see the LinkedIn Authorization page to grant access to your website to access his/her LinkedIn data. Once the user click authorized, LinkedIn will redirect him/her back to your callback URL, which ishttp://www.example.com/linkedin_callback.php in this example. LinkedIn will pass you some parameters so that you can proceed to Part 2 - Getting The Access Token.

Congrats! You have completed the first part of OAuth Authentication! With understanding the above steps, you should have no problem in implementing the rest of the things like getting the access token, and accessing LinkedIn API. I will be working on Part 2 - Getting The Access Token very soon to show that it is all very similar.
Update: I have posted Part II - Getting The Access Token.

0 commentaires:

Enregistrer un commentaire

 
-