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

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

Part II: Getting LinkedIn Access Token

This guide is a follow up from Part I: Redirecting User to LinkedIn. At this point, it is assume that we have gotten our LinkedIn Consumer Key and Consumer Secret as PHP constants LINKEDIN_KEY and LINKEDIN_SECRET respectively. We should have also gotten your request token and request token secret saved in session variables $_SESSION[‘linkedin_oauth_token’] and $_SESSION[‘linkedin_oauth_token_secret’].
In Part I, we ended with redirecting user to LinkedIn authorization page, after user login and granted access, he/she will be brought back to the callback URI we specified earlier on. LinkedIn will pass in some parameters in the URI as GET parameters. This guide is about the basic steps to get the access token in the callback script.
Step 1 - Validate Parameters Passed Back by LinkedIn
If everything is correct and user granted our website the access, LinkedIn will redirect him/her back to the callback URI with some parameters. The 2 important parameters are $_GET[‘oauth_token’] and $_GET[‘oauth_verifier’]. The $_GET[‘oauth_token’] should be the same as the request token we used pass to LinkedIn when redirecting user to the authorization page.  We start by making sure these parameters are there and the token is the same.
if (empty($_GET['oauth_token']) || empty($_GET['oauth_verifier']) || $_GET['oauth_token']!=$_SESSION['linkedin_oauth_token']) {
  echo 'You must grant us access to proceed on.'; exit();
}
Step 2 - Prepare OAuth Parameters
The require parameters are listed in the code. It is quite similar with those used in Part I, but without oauth_callback and with oauth_token and oauth_verifier.
$params = array(
  'oauth_consumer_key'=>LINKEDIN_KEY,
  'oauth_nonce'=>sha1(microtime()),
  'oauth_signature_method'=>'HMAC-SHA1',
  'oauth_timestamp'=>time(),
  'oauth_token'=>$_GET['oauth_token'],
  'oauth_verifier'=>$_GET['oauth_verifier'],
  'oauth_version'=>'1.0'
);
Step 3 - Prepare The Base String
This is the similar as Part I. But with the URL replaced by the access token URL. Notice that $links[‘access_token’] was defined in Part I, you need to re-define it in the callback script if you are separating the Part I and Part II code as 2 files. I will show how to combine Part I and Part II codes in one script at the end.
// 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['access_token']),
  urlencode_oauth($q)
);
$base_string = implode('&',$parts);
Step 4 - Get The Signature
Again, this step is quite similar to Part I. In Part I, we don’t have any token secret, so we ended up using only the Consumer Key concatenate with an empty string. Now, we need to make use of the request token secret we obtained and saved in session in Part I.
$key = urlencode_oauth(LINKEDIN_SECRET) . '&' . urlencode_oauth($_SESSION['oauth_token_secret']);
$signature = base64_encode(hash_hmac('sha1',$base_string,$key,true));
Step 5 - Put the Signature into Parameters and Prepare Authorization Header
This step is again similar to Part I with the POST request URL change to /uas/oauth/accessToken.
$params['oauth_signature'] = $signature;
$str = array();
foreach ($params as $key=>$value) {
  $str[] = $key . '="'.urlencode_oauth($value).'"';
}
$str = implode(', ',$str);
$headers = array(
  'POST /uas/oauth/accessToken HTTP/1.1',
  'Host: api.linkedin.com',
  'Authorization: OAuth '.$str,
  'Content-Type: text/xml;charset=UTF-8',
  'Content-Length: 0',
  'Connection: close'
);
Step 6 - Send POST Request To LinkedIn
This step is exactly the same as Part I.
$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. The response is quite similar to Part I as well.
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=cd87b123-7623-8fdf-8k6k-73oef1e27a26&oauth_token_secret=1fe0345e-999d-431f-9ae6-9b55fe255c41&oauth_expires_in=0&oauth_authorization_expires_in=0
Step 7 - Parse the Response to Get The Access 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 access token and secret.'; exit();
}
parse_str($parts[1],$data);
if (empty($data['oauth_token'])) {
  echo 'Failed to get LinkedIn access token.'; exit();
}
Step 8 - Save the Request Token and Secret
At this point, you should have gotten the user access token and access token secret in $data[‘oauth_token’] and $data[‘oauth_token_secret’] respectively. You need to save them as you need to use them in the rest of LinkedIn API to perform protected request like getting user LinkedIn information, posting Shares on behave of user and etc. For this example, I will save it in session, you may in fact, saved it in MySQL database as LinkedIn access token and access token secret do not expire (based on the return above).
$_SESSION['linkedin_access_token'] = $data['oauth_token'];
$_SESSION['linkedin_access_token_secret'] = $data['oauth_token_secret'];

// unset the Request Token (not needed anymore)
unset($_SESSION['linkedin_oauth_token']);
unset($_SESSION['linkedin_oauth_token_secret']);
Combining Part I and Part II
So far, we have discussed Part I and Part II separately. You can combine Part I and Part II in a single script with some control logic.
// Defining all the constants, function and links here
// --- Step 1, 2 and 3 of Part I ---

// Use validation logic in Step 1 of Part II to decide if it
// it is a callback or direct access
if (empty($_GET['oauth_token']) || empty($_GET['oauth_verifier']) || $_GET['oauth_token']!=$_SESSION['linkedin_oauth_token']) {
  // Do the remaining Step 4 and onward of Part I to redirect user to LinkedIn authorization page
  // --- Step 4 and onward of Part I ---
}

// At this point you should have the Request Token in session already.
// Use the Request Token to obtain the Access Token
// --- Step 2 and onward of Part II ---
Important Observation in Part I and Part II
You should have noticed that Part I and Part II is quite similar. For Part I, we started without any token and token secret. So, we used Consumer Secret and empty token secret for signing the base string and did not pass any token to request for the temporary token known as Request Token from LinkedIn. For Part II, we have already gotten the Request Token. Thus, we used Consumer Secret and Request Token Secret to sign the base string. We passed in the request token when requesting for Access Token - the ‘ultimate’ token we wanted to get. Once you get the Access Token, the Request Token has no other use and can be deleted. In fact, for the rest of LinkedIn API, you will be doing similar things as in Part II. To access protected LinkedIn resources or perform action on behalf of user in LinkedIn, you will use Consumer Secret and Access Token Secret to sign the base string and pass in the Access Token when performing GET,POST or PUT request to LinkedIn.
I will write the Part III that showing examples of how to do some common requests like getting user information and posting Share. Follow me in Tumblr if you would like to get notify when it is up.

0 commentaires:

Enregistrer un commentaire

 
-