Skip to content
World Wide Web Server edited this page Jul 4, 2012 · 15 revisions

Category:Helper::OAuth I wrote this helper to assist with OAuth authentication for the youtube api but it should work for any OAuth authentication. All it does is correctly sign your OAuth parameters that should be put in an http header and sent to whatever you are authenticating against.

One thing to note. It seems that google does not correctly build their HMAC-SHA1 hashes so if you are authenticating with them it is recommended that you use RSA-SHA1. Visit this link:

http://code.google.com/apis/gdata/docs/auth/authsub.html#Registered

to learn how to create an RSA-SHA1 certificate that you can upload to google.

Here is the OAuth section of the youtube api:

http://code.google.com/apis/youtube/2.0/developers_guide_protocol_oauth.html

And here is a helpful tool google provides to see what your OAuth header should look like:

http://googlecodesamples.com/oauth_playground/

[code] <?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**

  • Signs an array of oauth parameters according to the 1.0 spec using

  • the hmac-sha1 hasing algorithm

  • @param string $method either GET or POST

  • @param string $baseurl the baseurl we are authenticating againts

  • @param string $secret the consumer secret key

  • @param array $parameters all parameters that need to be signed (NOTE: the token secret key should be added here)

  • @return string the signature */ function sign_hmac_sha1($method, $baseurl, $secret, array $parameters) { $data = $method.'&'; $data .= urlencode($baseurl).'&'; $oauth = ''; ksort($parameters); //Put the token secret in if it does not exist. It //will be empty if it does not exist as per the spec. if(!array_key_exists('oauth_token_secret', $parameters))$parameters['oauth_token_secret'] = ''; foreach($parameters as $key => $value) { //Don't include the token secret into the base string if(strtolower($key) != 'oauth_token_secret')$oauth .= "&{$key}={$value}"; }
    $data .= urlencode(substr($oauth, 1)); $secret .= '&'.$parameters['oauth_token_secret'];

    return hash_hmac('sha1', $data, $secret); }

/**

  • Signs an array of oauth parameters according to the 1.0 spec using

  • the rsa-sha1 hasing algorithm

  • @param string $method either GET or POST

  • @param string $baseurl the baseurl we are authenticating againts

  • @param string $certfile the location of your private certificate file

  • @param array $parameters all parameters that need to be signed

  • @return string the signature */ function sign_rsa_sha1($method, $baseurl, $certfile, array $parameters) { $fp = fopen($certfile, "r"); $private = fread($fp, 8192); fclose($fp);

    $data = $method.'&'; $data .= urlencode($baseurl).'&'; $oauth = ''; ksort($parameters);

    foreach($parameters as $key => $value) $oauth .= "&{$key}={$value}"; $data .= urlencode(substr($oauth, 1));

    $keyid = openssl_get_privatekey($private); openssl_sign($data, $signature, $keyid); openssl_free_key($keyid);

    return base64_encode($signature); }

/**

  • Assembles the auth params array into a string that can
  • be put into an http header request.
  • @param array $authparams the oauth parameters
  • @return string the header authorization portion with trailing \r\n */ function build_auth_string(array $authparams) { $header = "Authorization: OAuth "; $auth = ''; foreach($authparams AS $key=>$value) { //Don't include token secret if($key != 'oauth_token_secret')$auth .= ",{$key}="{$value}""; } return $header.substr($auth, 1)."\r\n"; }

/**

  • Assemble an associative array with oauth values

  • @param string $baseurl the base url we are authenticating against.

  • @param string $key your consumer key

  • @param string $secret either your consumer secret key or the file location of your rsa private key.

  • @param array $extra additional oauth parameters that should be included (you must urlencode, if appropriate, before calling this function)

  • @param string $method either GET or POST

  • @param string $algo either HMAC-SHA1 or RSA-SHA1 (NOTE: this affects what you put in for the secret parameter)

  • @return array of all the oauth parameters */ function build_auth_array($baseurl, $key, $secret, $extra = array(), $method = 'GET', $algo = 'RSA-SHA1') { $auth['oauth_consumer_key'] = $key; $auth['oauth_signature_method'] = $algo; $auth['oauth_timestamp'] = time(); $auth['oauth_nonce'] = md5(uniqid(rand(), true)); $auth['oauth_version'] = '1.0';

    $auth = array_merge($auth, $extra); if(strtoupper($algo) == 'HMAC-SHA1')$auth['oauth_signature'] = sign_hmac_sha1($method, $baseurl, $secret, $auth); else if(strtoupper($algo) == 'RSA-SHA1')$auth['oauth_signature'] = sign_rsa_sha1 ($method, $baseurl, $secret, $auth);

    $auth['oauth_signature'] = urlencode($auth['oauth_signature']); return $auth; }

/**

  • Creates the authorization portion of a header NOTE: This does not
  • create a complete http header. Also NOTE: the oauth_token parameter
  • should be passed in using the $extra array.
  • @param string $baseurl the base url we are authenticating against.
  • @param string $key your consumer key
  • @param string $secret either your consumer secret key or the file location of your rsa private key.
  • @param array $extra additional oauth parameters that should be included (you must urlencode a parameter, if appropriate, before calling this function)
  • @param string $method either GET or POST
  • @param string $algo either HMAC-SHA1 or RSA-SHA1 (NOTE: this affects what you put in for the secret parameter)
  • @return string the header authorization portion with trailing \r\n */ function get_auth_header($baseurl, $key, $secret, $extra = array(), $method = 'GET', $algo = 'RSA-SHA1') { $auth = build_auth_array($baseurl, $key, $secret, $extra, $method, $algo); return build_auth_string($auth); }

/* ./system/application/helpers/oauth_helper.php */ ?>

[/code]

To generate the authorization header portion, something like this: [code] Authorization: OAuth oauth_version="1.0", oauth_nonce="3bb1d3ad600bc8132081261ffe5b4f01", oauth_timestamp="1283674744", oauth_consumer_key="example.com", oauth_callback="http://googlecodesamples.com/oauth_playground/index.php", oauth_signature_method="RSA-SHA1", oauth_signature="Tk6KiZltHoH/41xMmI2UyCXTA8BgzMFbFEAGCKBPDKqI8Rsjg/UYqh+Edi/KY2UoqCwxb3K+WYNGSaaUy/klzQ1/lSIXgXcVjI7QP7Bc6/xMmBauj/eWVjnEWJ2mbcfhIE1LrkJbqUjUsFnel2yGvwCykHS+A4mFM3y3xEtuJ8s=" [/code]

You would make a token request call like this: [code] echo get_auth_header('https://www.google.com/accounts/OAuthGetRequestToken', 'example.com', './path/to/private/cert', array('oauth_callback'=>urlencode('http://googlecodesamples.com/oauth_playground/index.php'))); [/code] It should be noted though that google requires an addtional "scope" parameter which does not go in with the authorization parameters but does get signed with them. The best way to understand how to put that in the header is to check out the oauth playground. So this example will not work in real life if authenticating with google. I use CUrl to connect to google and send my data across.

To build a full request header for the google youtube api do this:

[code] $baseurl = 'https://www.google.com/accounts/OAuthGetRequestToken'; $auth = build_auth_array($baseurl, 'example.com', './path/to/private/cert', array('scope'=>urlencode('https://gdata.youtube.com'))); $str = ''; foreach($auth AS $key=>$value) if($key != 'scope')$str .= ",{$key}="{$value}"";//Do not include scope in the Authorization string. $str = substr($str, 1);//Remove leading ,

$ch = curl_init("{$baseurl}?scope={$auth['scope']}"); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ; curl_setopt($ch, CURLOPT_SSLVERSION,3); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: OAuth {$str}")); $response = curl_exec($ch); curl_close($ch); return $response; [/code]

Play around with this helper and let me know what you think.

-UPDATE: Fixed issue where oauth_token_secret was not getting hashed with consumer_secret for HMAC signatures.

Clone this wiki locally