OAuth for Google

Derek Jones edited this page Jul 5, 2012 · 14 revisions
Clone this wiki locally

Category:Libraries::OAuth Category:Library::OAuth

[strong]NOTE: I have moved the code for this project to GitHub the url is: https://github.com/jimdoescode/CodeIgniter-YouTube-API-Library Please use this wiki page as a reference for how to implement the library but make sure you get the latest version from GitHub.[/strong]

I wrote this library to work with the youtube api. It will let you get an OAuth Request token, authorize the request token, then retrieve an access token. It should be noted that you have to have OAuth setup with google before this will work.

This library uses a helper I wrote in conjunction and have already posted on this wiki. It can be found at http://codeigniter.com/wiki/OAuth_Helper/ it needs to be included if you want to use this library as it does all of the signing. Also read what I posted about it for some helpful tips/sites.

In theory you can use this library to authenticate with all of the different services google offers that use OAuth however I have not tested this the only service that I have tested against is YouTube. That aside though supposedly all you would need to do to authenticate with a different service would be to specify a different 'scope' constant. All of the other constants would remain the same.

For those not familiar with OAuth it is a means of authenticating with another web service without having to store the users username and password for the other service on your site. You can read more about it at http://oauth.net/

To do this action requires first that a site sends a request to the service in question to retrieve a request token. The site must then redirect to the service and provide the request token to have the user authorize it. Once the user authorizes the request token they are redirected back to your site which is then given authorized oauth token as well as the oauth verifer. These values can then be exchanged for an access token which is what is used to make authenticated requests on the users behalf. This might seem like a lot and to some degree it is but the user only sees a fraction of this, and the whole experience is pretty seamless.

Now I will show you how to use the code first you want to initialize the library and pass in your consumer key and secret. Your key is defined by google after you confirm your OAuth account, it tends to be your base url without the www.

So example.com would be the key for http://www.example.com

Your consumer secret can either be defined by google if you have elected to use HMAC-SHA1 as your signing algorithm. If you chose RSA-SHA1 as your signing algorithm it would be the file path to your .pem file which is the signing certificate you would upload to google. Read the doc I wrote on the helper for links on how to generate these files.

If you decide to use RSA-SHA1 I suggest making your .pem inaccessible using an htaccess file restriction or something. If someone figures out your secret whether RSA or HMAC your users are compromised so keep it safe and secure.

I was unable to get HMAC signatures to work with google so I ended up going with RSA (I later realized I was missing some stuff from my HMAC signature and fixed my helper but by then I was already using RSA.) Much of the library defaults to RSA as the signing algorithm so if you want to make things easier on your self I would use that.

Here is the first call to load the library (I put my key and secret into a config file for easy access and changing):



$params['key'] = $this->config->item('google_consumer_key');
$params['secret'] = $this->config->item('google_consumer_secret');
$this->load->library('google_oauth', $params);

You can change the signing algorithm and http method by setting the following in your params array.


$params['method'] = "POST";
$params['algorithm'] = "HMAC-SHA1";

If you do not define these parameters they default to GET and RSA-SHA1 respectively.

Next we will start by getting a request token


$service_url = $this->google_oauth->get_request_token(site_url("/user/youtube_access"));
redirect($service_url);

You need to specify a url to redirect back to after the user has authorized the request token. This method will return a url to the service you wish to authenticate with all you need to do is redirect to the service url.

NOTE: If you are using HMAC signing then the get_request_token method will return an array with keys "token_secret" and "redirect". You will want to temporarily store the token secret value as you will use it in the access step. Then redirect to the "redirect" value.

After this things go out of your hands your user is presented with a page to login to the service in question and then they must click a button to approve access of your site to the service. If they deny access you wont be able to make authenticated requests.

Assuming we are successful the service redirect back to our site to the url we specified. In this case its http://www.example.com/index.php/user/youtube_access but at the end of this url they have tacked on an oauth_token and oauth_verifier. I tried using all kinds of things to get at these but since CI doesn't offer much support for GET I was finally successful with parsing $_SERVER['REQUEST_URI']. Anyway if you are able to get at these variables you can pass them into the access method if not it will attempt to get them itself so its probably best if you just let it do its thing. We need to reload the library since we left our site.


$params['key'] = $this->config->item('google_consumer_key');
$params['secret'] = $this->config->item('google_consumer_secret');

$this->load->library('google_oauth', $params);
$oauth = $this->google_oauth->get_access_token();

NOTE: If you are using HMAC signing you need to specify the token_secret you got from the request step as the second parameter of this method. So


$oauth = $this->google_oauth->get_access_token(false, $token_secret);

The access method will return an array with keys of 'oauth_token', and 'oauth_token_secret' These values are your access token and your access token secret. You should store these in your database.

Now you have an access token and can make google service requests on your users behalf. You should know that users can revoke access at any time rendering your token useless. Also if you decide to use RSA as your signing method you do not need the token secret that is only necessary if you are using HMAC.

Here are both methods from my controller (I use RSA signing):


public function youtube_request()
{
    $params['key'] = $this->config->item('google_consumer_key');
    $params['secret'] = $this->config->item('google_consumer_secret');

    $this->load->library('google_oauth', $params);
    redirect($this->google_oauth->get_request_token(site_url("/user/youtube_access")));
}

public function youtube_access()
{
    $params['key'] = $this->config->item('google_consumer_key');
    $params['secret'] = $this->config->item('google_consumer_secret');

    $this->load->library('google_oauth', $params);
    $oauth = $this->google_oauth->get_access_token();

    $this->_store_in_db('youtube_token', $oauth['oauth_token']);
    $this->_store_in_db('youtube_secret', $oauth['oauth_token_secret']);
        
    redirect(site_url());
}

If you were going to use HMAC signing it would look like this:



public function youtube_request()
{
    $params['key'] = $this->config->item('google_consumer_key');
    $params['secret'] = $this->config->item('google_consumer_secret');
    $params['algorithm'] = "HMAC-SHA1";

    $this->load->library('google_oauth', $params);
    $response = $this->google_oauth->get_request_token(site_url("/user/youtube_access"));
    
    $this->_store_somewhere($response['token_secret']);

    redirect($response['redirect']);
}

public function youtube_access()
{
    $params['key'] = $this->config->item('google_consumer_key');
    $params['secret'] = $this->config->item('google_consumer_secret');
    $params['algorithm'] = "HMAC-SHA1";    

    $this->load->library('google_oauth', $params);

    $token_secret = $this->_get_from_storage('token_secret');

    $oauth = $this->google_oauth->get_access_token(false, $token_secret);

    $this->_store_in_db('youtube_token', $oauth['oauth_token']);
    $this->_store_in_db('youtube_secret', $oauth['oauth_token_secret']);
        
    redirect(site_url());
}

Let me know if you have any questions in the comments. I will be releasing a YouTube api once I get the code cleaned up a bit that will incorporate the OAuth access token you retrieve. So keep an eye out for that.

-UPDATE: Changed the library a bit to better handle HMAC signing. I did not test it for google though. I'm using similar techniques for a twitter oauth library and things seem to be working fine. Also linked to my blog where the most up-to-date version of the library can be found incase I let this wiki page fall into disrepair.

-UPDATE: I can confirm that the library does work with HMAC signing and google.