2 Legged OAuth in PHP


Google Apps Premier/Education administrators can take advantage of 2 legged OAuth to communicate with the Google Data APIs. This sample makes use of the PHP OAuth library from oauth.net.
<?php
require_once('OAuth.php');

// Establish an OAuth consumer based on our admin 'credentials'
$CONSUMER_KEY = 'yourdomain.com'; 
$CONSUMER_SECRET = 'YOUR_CONSUMER_SECRET'; 
$consumer = new OAuthConsumer($CONSUMER_KEY, $CONSUMER_SECRET, NULL);

// Setup OAuth request based our previous credentials and query
$user= 'any.user@yourdomain.com';
$base_feed = 'http://www.google.com/m8/feeds/contacts/default/full/';
$params = array('max-results' => 10, 'xoauth_requestor_id' => $user);
$request = OAuthRequest::from_consumer_and_token($consumer, NULL, 'GET', $base_feed, $params);

// Sign the constructed OAuth request using HMAC-SHA1
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, NULL);

// Make signed OAuth request to the Contacts API server
$url = $base_feed . '?' . implode_assoc('=', '&', $params);
echo send_request($request->get_normalized_http_method(), $url, $request->to_header());
 
/**
 * Makes an HTTP request to the specified URL
 * @param string $http_method The HTTP method (GET, POST, PUT, DELETE)
 * @param string $url Full URL of the resource to access
 * @param string $auth_header (optional) Authorization header
 * @param string $postData (optional) POST/PUT request body
 * @return string Response body from the server
 */
function send_request($http_method, $url, $auth_header=null, $postData=null) {
  $curl = curl_init($url);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_FAILONERROR, false);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

  switch($http_method) {
    case 'GET':
      if ($auth_header) {
        curl_setopt($curl, CURLOPT_HTTPHEADER, array($auth_header)); 
      }
      break;
    case 'POST':
      curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/atom+xml', 
                                                   $auth_header)); 
      curl_setopt($curl, CURLOPT_POST, 1);                                       
      curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
      break;
    case 'PUT':
      curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/atom+xml', 
                                                   $auth_header)); 
      curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
      break;
    case 'DELETE':
      curl_setopt($curl, CURLOPT_HTTPHEADER, array($auth_header)); 
      curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method); 
      break;
  }
  $response = curl_exec($curl);
  if (!$response) {
    $response = curl_error($curl);
  }
  curl_close($curl);
  return $response;
}

/**
 * Joins key:value pairs by inner_glue and each pair together by outer_glue
 * @param string $inner_glue The HTTP method (GET, POST, PUT, DELETE)
 * @param string $outer_glue Full URL of the resource to access
 * @param array $array Associative array of query parameters
 * @return string Urlencoded string of query parameters
 */
function implode_assoc($inner_glue, $outer_glue, $array) {
  $output = array();
  foreach($array as $key => $item) {
    $output[] = $key . $inner_glue . urlencode($item);
  }
  return implode($outer_glue, $output);
}
?>

41 comments:

Javier Alvarez said...

Great example !!
Could you post another php example (or link) to add a new contact using HTTP POST ?
I'm trying, but I have problems :-(
Thanks in advance.
Regards.

Eric (Google) said...

The Contacts API is not supported in the Zend PHP client library, but you can send over raw XML. You can use the example @ http://code.google.com/apis/contacts/developers_guide_protocol.html#Creating for $contactEntry.

// setup same as before
params = array('xoauth_requestor_id' => $user);
$request = OAuthRequest::from_consumer_and_token($consumer, NULL, 'POST', $base_feed, $params);
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, NULL);

$url = $base_feed . '?' . implode_assoc('=', '&', $params);
echo send_request($request->get_normalized_http_method(), $url, $request->to_header(), $contactEntry);

Javier Alvarez said...
This comment has been removed by the author.
Javier Alvarez said...

Thanks for your help!!
I was not using the parameters properly. I had to use another $base_feed and I used and access_token (previously autorized by user). Something like this:

$CONSUMER_KEY = 'yourdomain.com';
$CONSUMER_SECRET = 'YOUR_CONSUMER_SECRET';
$consumer = new OAuthConsumer($CONSUMER_KEY, $CONSUMER_SECRET, NULL);
$token = new OAuthConsumer($access_token, $access_token_secret);
$user= 'any.user@yourdomain.com';
$url_base = "http://www.google.com/m8/feeds/contacts/".urlencode($user)."/full";
$request = OAuthRequest::from_consumer_and_token($consumer, $token, 'POST', $url_base, $params);
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, $token);
$url = $url_base . '?' . implode_assoc('=', '&', $params);
echo send_request($request->get_normalized_http_method(), $url, $request->to_header());

Eric (Google) said...

Just so anyone following knows, Javier's code is correct, but uses 3 Legged OAuth instead of 2 Legged. With 2 Legged OAuth, there's no access token.

See http://code.google.com/apis/accounts/docs/OAuth.html#GoogleAppsOAuth

Owen said...

If anyone has an example for how this can be used I'd love to see it. I'm not sure I really understand what the potential uses are.

Eric (Google) said...

This page lists use cases:
http://code.google.com/apis/accounts/docs/OAuth.html#GoogleAppsOAuth

For example, as a domain admin you could up load an HR document to every users' Google Docs account, add/update a particular business contact, or add a company event to their Calendar. That's all without their prior approval.

Sirhc Senots said...

Hey Eric what license is this example code posted under?

Eric (Google) said...

Apache 2.0 License

Eric said...

Hi,

Nice, It's working very well...
Can I use it to list the last unread messages ?
I didn't find it yet...

Thanks
Éric (but another !)

Eric (Google) said...

If you're asking about the Gmail Atom feed + 2 legged oauth, the answer is no.

http://code.google.com/p/gdata-issues/issues/detail?id=1264

Eric said...

Thanks for your answer...
Looking for that a few hours today...
And I didn't yet find how to print unread mail list in a php page without having the user password writing clearly... (with Oauth for exemple)

If you have some idea...

Thanks again
Éric (NOT the google one ;-) )

Hubert said...

this code does not work with the calendar.

I think that the calendar does not work wiht OAuth at all. I always get the same message: "Unknown authorization header" (Error code 401)

I tested 3-legged OAuth.

Would you mind to test calendar with your code? Thanks




By the way, useful for curl connector would be to use following to follow redirects:
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);

Eric (Google) said...

Ah yes, I'm always careful not to use Calendar in OAuth examples. :)

I believe the issue is the 302 redirect Calendar returns (if you don't include a gsessionid). You'll need to re-issue the request with the URL calendar returns in the redirect. This code does not resign the redirect request.

Hubert said...

> I believe the issue is the 302 redirect
> Calendar returns (if you don't include
> a gsessionid). You'll need to re-issue
> the request with the URL calendar
> returns in the redirect. This code does
> not resign the redirect request.

Sorry, did I understand you correctly:
Calendar works/should work with gsession in the url?

I am doing that but no success:
[request] => GET /calendar/feeds/default/allcalendars/full?gsessionid=lmeVZfrpWnoUz-RlEfBafg? HTTP/1.0
Authorization: OAuth realm="",
oauth_consumer_key="www.example.com",
oauth_nonce="e4287b9e5a18b403c51bc9d21ac64f7a",
oauth_signature="9vmOxdfGAF9%2FV9%2BXDlM4gyE7VXM%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1255082495",
oauth_token="1%2FsxeOZWLy8nN8Tbt0lVAeR2ATiaQZnWPB51nTvo8n9Sw",
oauth_version="1.0"
Accept: application/atom+xml, text/html; q=0.3, application/xhtml+xml; q=0.5
Content-Type: application/x-www-form-urlencoded
Host: www.google.com
Accept-Language: en,en-us;q=0.8,de;q=0.7,de-de;q=0.5,bs;q=0.3,sr;q=0.2
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Content-Length: 0


answer:
Unknown authorization header
Error 401


Thanks

Hubert said...

my mistake.

I resigned it and everything was perfect.

Thanks for the hint

Pork Chop said...

How can I take the $request (in the example) after signing and use it as an httpClient with Zend_Gdata? All of the Gdata functions require a $client and I'd like to use one that has been authenticated with this type of 2 legged Oauth. Thanks.

Eric (Google) said...

Check out this sample:
http://code.google.com/p/gdata-samples/source/browse/trunk/hybrid/index.php#106

Whiz-Solutions said...

Hi All,

Thanks for sharing the example, but when trying to run the code I am getting Token invalid - Invalid AuthSub token. Error 401.

I have registered my application on google and am using the consumer key and secret given to me.

Can anyone help me out?

Thanks,
Anil

Алексей Руденко said...

Hello,
thanks for example! But there's one questions - how can I retrieve contact emails? They are not displayed currently - I can get only contact names.
Thanks a lot

Reese said...

"I resigned it and everything was perfect".

How do you re-sign it? Where do you get the URL calendar returns?

Daniel Gleckler said...

If I wanted to POST a document/image file up using this method, how would I format my $postData?

I'm getting a "Content is not allowed in prolog." response from the server if I just pass $_FILES['myfile'];

Mohd said...

I am getting Token invalid - Invalid AuthSub token. Error 401.


What's going wrong?

Francois said...

So line 10 to 16 must be executed before EACH command to the API ?

madhuri said...

It was a great example my fren.I was trying out a lot with many PHP examples but I haven't succeeded with the coding.In web design company had made with reference to Javier's code using 3 legged OAuth.

sunitha said...

Several things in here' haven't considered before.Thank you for making this type of awesome publish that is really perfectly written, is going to be mentioning lots of buddies relating to this. Maintain blogging. joomla websites | joomla development

Lalit said...

hey buddy i want to implement google calendar by using this code.. so what changes is needed to implement google calendar to fetch feeds data

Anonymous said...

It is not working at alll

Anonymous said...

The code is not working at all!!!!!! Giving error

Anonymous said...

401. That's an error.is showing

Anonymous said...

please help!!!!!!!!!!!!!! I am getting the following error


{"version":"2","status":"error","error":"Your sort parameter cannot be parsed. Please see http:\/\/wiki.developer.factual.com\/Server-API for documentation.","error_type":"Api::Error::InvalidArgument"}

Azadi said...

Just used this code as a base to add owners to about 1000 Google sites under our school domain - worked a treat!

However, updating ACL entries (PUT requests) kept failing. I had to add If-Match:* header to the requests by modifying the corresponding line of send_request() function to:

curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/atom+xml', 'If-Match:*', $auth_header));

kosovohp said...

Girl Xinh | Hot Girl | Cute Girl | Sexy Girl | Hot Girl Asian
Hot Girl | Lexi Belle | Sexy Girl | Cute Girl | Hot Asian Girl | Leah Dizon | Hot Girl Asian | Girl Xinh
socks proxy | socks5 | proxy free |proxy list

epictoon said...

So that is how you simply do it. .... Thanks for the code :)
delicious


Cisgirin said...
This comment has been removed by the author.
ansley dias said...

how can we use this to fetch calendars?

martid95 said...

Someone can add a new email to gmail contacts using OAuth 2.0 and PHP?

Đào Quân said...

dich vu lam bao cao tai chinh tai my dinh
dich vu lam bao cao tai chinh tai hai ba trung
dich vu lam bao cao tai chinh tai ba dinh
dich vu lam bao cao tai chinh tai thanh tri
dich vu lam bao cao tai chinh tai hoang mai
dich vu lam bao cao tai chinh tai tay ho
dich vu lam bao cao tai chinh tai dong da
==========
dich vu ke toan thue tai dong da
dich vu ke toan thue tai tay ho
dich vu ke toan thue tai bac ninh
dich vu ke toan thue tai hai ba trung
dich vu ke toan thue tai tu liem
dich vu ke toan thue tai hoang mai
dich vu ke toan thue tai ba dinh
dich vu ke toan thue tai thanh tri
dich vu ke toan thue tai thai binh
cong ty lam dich vu ke toan tai vinh phuc
cong ty dich lam vu ke toan tai hung yen
cong ty dich lam vu ke toan tai phu tho
cong ty lam dich vu ke toan tai hai duong
cong ty lam dich vu ke toan tai hai phong
cong ty lam dich vu ke toan tai bac ninh
dich vu ke toan tai vinh phuc
dich vu ke toan tai hung yen
dich vu ke toan tai hai duong

Đào Quân said...

dich vu ke toan tai tay ho
dich vu ke toan tai ba đinh
dich vu ke toan tai hoang mai
dich vu ke toan tai thanh tri
dich vu ke toan tai dong da
dich vu ke toan tai tu liem
dich vu ke toan tai ha dong
dich vu ke toan tai long bien
dich vu ke toan tai thanh xuan
dich vu ke toan tai hai phong
dich vu ke toan tai bac ninh
dich vu ke toan tai hai ba trung
dich vu ke toan tai dong anh
dich vu ke toan tai gia lam
dich vu ke toan tai ung hoa
dich vu ke toan tai quoc oai
dich vu ke toan tai son tay
dich vu ke toan tai thanh oai
hoc ke toan tong hop
dich vu ke toan thue tron goi
dich vu bao cao tai chinh
dia chi hoc ke toan tong hop
khoa hoc ke toan tong hop
hoc chung chi ke toan
dich vu ke toan thue tai tphcm
lớp học kế toán tổng hợp
lớp học kế toán thực hành

Đào Quân said...

dia chi hoc ke toan tai cau giay
dia chi hoc ke toan tai ha dong
dia chi hoc ke toan tai bac ninh
trung tam dao tao ke toan tai ha dong
trung tam dao tao ke toan tai cầu giấy
trung tam dao tao ke toan tai thanh xuan
trung tam dao tao ke toan tai tphcm
khóa học kế toán tổng hợp tại hải phòng
khóa học kế toán tổng hợp tại tại bắc ninh
khóa học kế toán tổng hợp tại tphcm
khóa học kế toán tổng hợp tại hà nội
trung tam dao tao ke toan tai quan 3
trung tam dao tao ke toan tai binh duong
trung tam dao tao ke toan tai bac ninh
trung tam dao tao ke toan tai hai phong

Đào Quân said...

dich vu ke toan thue tai quan 12
dich vu ke toan thue tai quan 11
dich vu ke toan thue tai quan 10
dich vu ke toan thue tai quan 9
dich vu ke toan thue tai quan 8
dich vu ke toan thue tai quan 7
dich vu ke toan thue tai quan 6
dich vu ke toan thue tai quan 5
dich vu ke toan thue tai quan 4
dich vu ke toan thue tai quan 3
dich vu ke toan thue tai quan 2
dich vu ke toan thue tai quan 1
dich vu ke toan thue tai quan tan phu
dich vu ke toan thue tai quan binh tan
dich vu ke toan thue tai quan phu nhuan
dich vu ke toan thue tai quan tan binh
dich vu ke toan thue tai quan go vap
dich vu ke toan thue tai quan thu duc
dich vu ke toan thue tai quan binh thanh
dich vu ke toan thue tai huyen can gio
dich vu ke toan thue tai huyen nha be
dich vu ke toan thue tai huyen binh chanh
dich vu ke toan thue tai huyen hoc mon
dich vu ke toan thue tai huyen cu chi
dich vu ke toan thue tai huyen can gio