Login   Register  
PHP Classes
elePHPant
Icontem

Painless OAuth with PHP - PHP OAuth API package blog

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  All package blogs All package blogs   PHP OAuth API PHP OAuth API   Blog PHP OAuth API package blog   RSS 1.0 feed RSS 2.0 feed   Blog Painless OAuth with PHP  
  Post a comment Post a comment   See comments See comments (60)   Trackbacks (0)  
>> Next: Offline Access to Goo...

Author: Manuel Lemos

Posted on:

Package: PHP OAuth API

OAuth is a widely used protocol to access APIs of certain Web sites on behalf of users of those sites.

Despite OAuth is relatively easy to explain, it is not easy to implement it without dealing with the headaches of the multiple protocol settings, the different protocol versions, the details of specific site implementations, and the worst of all having to know more about the details of the protocol than you would like to care.

Read this article to learn how to use this PHP OAuth API class to access any API of any site that supports any version of OAuth without having any of those headaches.




Contents

Why the OAuth protocol is necessary?

How does the OAuth protocol works?

PHP OAuth consumer implementations

Using the PHP OAuth API class in practice

Conclusion

Why the OAuth protocol is necessary?

PHP + OAuth released under the Creative Commons Attribution ShareAlike 3.0 licenseIf you are already familiar with the OAuth protocol or you do not care much about its reason of existence, you may want to skip to the section below named Using the PHP OAuth API class in practice.

Consider one user that is registered to one site, lets call it the provider or server site.Think for instance of Twitter as an example of a provider site.

The user can do many things in the consumer site pages directly, like for instance posting new status messages in Twitter. Alternatively many of those things can be done accesing the Twitter API from programs running in other sites. Lets call those other sites consumer or client sites.

Programs accessing the Twitter site from consumer sites can post new Twitter status messages on behalf of the user, as if it was the user entering them in the Twitter site.

The original problem of this solution is that the user would have to provide his user name and password to the consumer sites, so they could access the APIs of the provider sites on their behalf.

This is a security problem because it allows eventual abuses from people behind consumer sites. Not only they can execute actions with the user accounts that they did not intend to allow, but the user names and passwords can be used to abuse other sites on which the users have accounts with the same passwords.

How does the OAuth protocol works?

OAuth is a protocol that was created to avoid the problems mentioned above. It allows a consumer site to access information or execute actions in a provider site with the user account but the user does not need to give the account password to the consumer site.

When a consumer site wants to access the user account of a provider site, using the OAuth protocol the user is redirected to a page in the provider site on which he is asked to grant certain account access permissions to the consumer site.

Then the user is redirected back to the consumer site in such a way that it can obtain a special token to access the provider site API with the permissions that the user granted.

If you are not familiar with the details of OAuth, let me tell you that this explanation of the protocol is an oversimplification. This class was created to deal with all the complications of the protocol so you do not need to learn and understand it to access provider site APIs. So this is all you need to know about how the protocol works.

PHP OAuth consumer implementations

Unfortunately, most of the existing PHP OAuth consumer solutions are much more complicated then they should be.

For instance, the PECL OAuth extension is very complete in terms of the functionality that is necessary to build OAuth based consumer or provider sites. However, using it is like having all the pieces of a large puzzle and guessing how each piece should be assembled to solve the whole puzzle.

There are multiple incompatible versions of the OAuth protocol. Without knowing how each version of the OAuth protocol works, you will not even get started with PECL OAuth to do anything.

Not only you need to know how the OAuth protocol works, but you also need to know the different steps of each of the OAuth protocol versions, what parameters you need to pass the this extension to compute the necessary information bits used in the protocol, as well when and where you need to redirect the user between the consumer and the provider site.

If you have already gone through this headache, you know It is a challenge to the patience of any developer.

I do not mean to put down the effort of the developers of the PECL OAuth extension. As I said, it is very complete in terms basic functionality. But in terms of usability for the developer that does not know the OAuth protocol in detail nor is interesting in learning more than enough about it, this extension could have provided a simpler way of usage. The same goes for many OAuth libraries out there in PHP or in other languages.

Using the PHP OAuth API class in practice

1. Don't make me learn the OAuth protocol

This PHP OAuth client class was built specifically with the purpose to get you up to speed without knowing much about how the protocol works.

It is always good to know how the protocol works internally but if you do not have the time nor the patience, you should not need to know the protocol extensively.

There are mainly two versions of OAuth protocol in use: version 1.0a and version 2.0. But do not worry, the class abstracts all the differences between those versions of the protocol, so you do not have to write multiple code sections depending on the version of the protocol supported by the provider site.

There are also differences of implementation and configuration when accessing specific OAuth provider sites. In most cases these differences will be transparent for you. The class is smart enough to deal with at least some of those differences, so you do not have to handle them in your application.

All you need to know is that the class does mainly two things: a) interact with a OAuth provider site to obtain an access token, b) call the API of the provider site to execute an API function using a previously obtained access token.

2. Introduction to the use case mapping aproach

Before explaining how to use the class for OAuth related purposes, it may be useful for those that like to study how stuff works internally to describe the approach I used in this and other classes that encapsulate functionality of what I call application level components.

If you prefer to learn from example code, you may skip this section to the step named Obtaining the access token.

The approach is called use case mapping. When you need to implement a software system, usually you divide it in sub-systems when the system is large enough. Each system or sub-system implements a set of use cases.

Use cases are individual situations that your systems need to handle to achieve their goals. Some people call use cases other names like screens or pages. For instance in a system you could have use cases like: registration page, login page, user options, newsletter delivery, etc.. 

For those familar with agile development modeling, use cases are somewhat similar to user stories. I prefer thinking in terms of use cases because sometimes you need to handle interactions between your system and an actor that is not a real user, like for instance an external system that your system needs to communicate with using some APIs.

Anyway, for the actual implementation of use cases I designed a pattern to implement them as classes. Each use case maps to a class, thus the use case mapping name of this approach.

The OAuth client class was implemented as a use case class. In this article I am only going to describe the public functions and variables of use case classes because it is all you need to know to use the OAuth client class.

Basically a use case class has 4 public functions and 2 public variables. There may be other public functions and variables specific to the purpose of the use case. For now let me explain the roles of the basic public functions and variables.

Functions

Initialize() - It is the first function you need to call after setting up a class object. It is not a constructor function. It is a function that initializes the object and evaluates whether certain mandatory conditions are valid, like for instance establishing a connection to the database.

These mandatory conditions are called preconditions. If one or more precondition is not met, the function returns false and an error variable is set to explain the reason of failure to the developer.

Process() - It is the function is where all the action happens. Its role is to process any input and prepare the generation of any output. In general the final output should not generated here.

It should be called only after calling the Initialize() function. If for some reason the processing fails, this function returns false and an error variable is set.

Finalize() - This function is meant to clean up any resources allocated during the Initialize and Process calls. Usually it is meant to assure that certain conditions are met at the end of the use case. Those conditions are called post-conditions. Generating log entries of all events that happened during the processing is an example of a post-condition.

This function should not be called if the Initialize function failed. It takes one parameter that is usually the return value of the call to the Process function. Again, if for some reason the finalization fails, this function returns false and an error variable is set.

Output() - This is where any output if the use case should be issued. The output may be generated from information produced during the call to the Process function. When necessary, private class variables may be used to share information between the Process and the Output calls.

This way you can implement the separation of concerns. No output happens during the processing, nor any processing happens during the output.

Usually the Output function does not return anything because the output is displayed to the user, but in some cases it can return a string with the actual output data if it is convenient.

Variables

$error - This is the variable that stores an error message if any of the functions Initialize, Process and Finalize fail. This error message is not meant to be displayed to the users. It is rather to let the developer know why it failed.

$exit - This boolean variable may be set by the use case class to tell whether the script should exit immediately without outputting anything. When this variable is true, the script should exit without calling the Output function. Usually this means that the class issued special headers like for instance those that redirect the browser to another page.

3. Obtaining the access token

OAuth is a complicated protocol that requires accessing the provider site API and redirecting the user browser back and forth between the consumer and provider sites. This interaction requires setting several parameters like the URLs of the provider site to access each thing.

Fortunately, this class provides built-in support some of the most popular provider sites. You only need to set single variable named $server with the type of server you want to access. This way the class automatically configures several of its variables, so you do not have to do it manually.

The class provides built-in support to many provider sites. More will be added in the future. However, if you need to access a OAuth server that is supported directly by the class, you can still use the class to access it. You just need to configure certain variables manually.

Configuring the class to access those other servers is outside the scope of this article. Read the class documentation to learn what you need to do. Feel free to ask questions in the class support forum if you have any difficulties.

So, your basic OAuth authorization script starts like this:


$client = new OAuth_client_class; $client->server = 'Twitter';

The next thing you need to do is to configure the identity of your applications. First you need to go to the provider site and register an application. The application registration will provide you values for the application identifier and an application secret. For security reasons, you should not share these application secret with anybody.


$client->client_id = 'Application identifier goes here'; $client->client_secret = 'Application secret goes here';

OAuth 2.0 servers may let you request permission to access to specific sections of the provider site API. These permissions should be configured using the $scope variable. For OAuth 1.0 provider sites, those permissions are usually configured in the application options page.

The values of the permissions to request depend on the provider site. You need to check the provider site API documentation to determine the permission values your application needs.


$client->scope = 'API permissions list goes here';

During the OAuth authorization process the user browser is redirect to the provider site. Then the browser is redirected back to the consumer site after the user grants access to your application. The provider site needs to know to what page the user should be redirected back.

Usually you can configure the URL of the page to redirect the user browser back to your consumer site using the $redirect_uri variable. Some servers require that this URL must be under a valid public domain. So private domains may not be accepted.


$client->redirect_uri = 'http://'.$_SERVER['HTTP_HOST']. dirname(strtok($_SERVER['REQUEST_URI'],'?')). '/change_this_to_the_name_of_this_script.php';

Now you are ready to initiate the OAuth process.


if(($success = $client->Initialize())) { if(($success = $client->Process())) {

After calling the Process function the OAuth authorization process may have been completed or not. If the process was completed, the $access_token variable is set to a non-empty string.

You may want to store the access token value somewhere for subsequent use. Usually applications store the token in a database so they can use it to call the provider site API later, eventually when the user is not present.

For OAuth 1.0a provider sites, there is an additional token secret value that you also need to keep. It is stored in the $access_token_secret variable.

     if(strlen($client->access_token))
     {
       // Do something useful with the access token
     }

If there was an error retrieving the access token, the $authorization_error variable is set to the error message.

     elseif(strlen($client->authorization_error))
     {
       $client->error = $client->authorization_error;
       $success = false;
     }
   } 

At the end, always call the Finalize function regardless if the authorization process was completed with success or not.

   $success = $client->Finalize($success);
 }

Then you need to check the $exit variable to determine if your script needs to exit immediately, so the OAuth process may work correctly.

 if($client->exit)
   exit;

If the process was completed successfully, you may want to show an useful message to the user.

 if($client->access_token)
 {
   echo '<h1>API access was authorized successfully!</h1>';
 }

You are also recommended to show useful messages to the user if the process failed for some reason.

 if($client->authorization_error)
 {
   echo '<h1>It was not possible to obtain API access',
        ' authorization!</h1>,
        '<p>Please <a href="?">try again</a>.</p>';
 }

4. Calling the provider site API

Once you have obtained the access token, you can call the provider site API immediately using the CallAPI function right after returning from the Process function and before calling the Finalize function.

Some provider sites also allow accessing their APIs on behalf of the user even when the user is not present. You just need to use the CallAPI function passing the previously obtained $access_token and $access_token_secret values.


$client->access_token = 'Access token here'; $client->access_token_secret = 'Access token secret here'; $url = 'https://api.twitter.com/1.1/account/verify_credentials.json'; $method = 'GET'; $parameters = array(); $options = array(); $success = $client->CallAPI($url, $method, $parameters, $options, $response)))

The $url, $method and $parameters of the API call are defined in the provider site API documentation. The $options parameter is an array with eventual options you may need to set to configure the way the API call is processed. Check this class documentation for more details on those options.

The $response parameter returns the the results of the API call. If the results are form URL encoded or JSON encoded, the CallAPI decodes the response value for you.

If the API call failed due to some problem related with the parameters or with the access token, the $access_token_error variable is set to the error message that you need to check.

Conclusion

Despite the complexity of the OAuth protocol and its different implementations, this class attempts to abstract as much as possible all the details, so applications only require a minimal amount of code to obtain authorization to call the provider site APIs.

In part this simplification of the process was achieved by adding built-in support to some of the most popular OAuth based server APIs. It is not possible to add built-in support to all APIs that exist out there. However, the class will continue to evolve to cover as many API as possible.

Another part of this simplification is related to the fact that the class is self-contained. This means that you only need to load this class to use all the provided functionality. The only external dependency is on an HTTP class (also available in this site) to send HTTP requests to the provider Web server. There are no other classes you need to load to use all the OAuth client functionality.

If you have read this article, tried to use this class, and still have any difficulties, feel free to post about your problem in the support forum so you can get help as soon as possible.

For other comments and questions, feel free to post a comment to this article.


You need to be a registered user or login to post a comment

Login Immediately with your account on:

Facebook ConnectGmail or other Google Account
Hotmail or Microsoft Windows LiveStackOverflow
GitHubYahoo


Comments:

11. Fitbit api calls - Lucas Bakalian (2014-05-19 09:13)
not able to run a script... - 8 replies
Read the whole comment and replies

12. Refresh access token with yahoo? - Kevin (2014-05-17 22:52)
How do you refresh the access tokens for yahoo?... - 0 replies
Read the whole comment and replies

10. Google drive api $parameters usage - Byju Chalad (2014-05-14 22:44)
Not able to configure drive api parameters to upload a file... - 9 replies
Read the whole comment and replies

9. Other OAuth Sites - Tom R (2014-04-08 02:12)
Other OAuth Sites... - 1 reply
Read the whole comment and replies

7. how can i add contact - Sohel Rana (2014-03-31 07:20)
its work fine for get contacts... - 8 replies
Read the whole comment and replies

8. g ok, fb ok, twitter problem - Mike Tommasi (2014-02-20 19:16)
twitter login: reload asks for auth again... - 2 replies
Read the whole comment and replies

6. worked fine but got 1 problem - Kalpit Pandit (2013-10-16 16:30)
It's showing same login info again n again... - 2 replies
Read the whole comment and replies

5. Double authorization request for Google - Marc-André Thiébaut (2013-06-05 12:00)
Double authorization request for Google... - 5 replies
Read the whole comment and replies

4. Redirect issue - Marcus Link (2013-02-28 12:13)
No redirect from OAuth server... - 8 replies
Read the whole comment and replies

3. Google OAuth offline access and Box api 'refresh tokens' - Steve Penn (2013-02-12 11:44)
Is there a way to gather the refresh token in the current class?... - 1 reply
Read the whole comment and replies


>> Next: Offline Access to Goo...


  Post a comment Post a comment   See comments See comments (60)   Trackbacks (0)  
  All package blogs All package blogs   PHP OAuth API PHP OAuth API   Blog PHP OAuth API package blog   RSS 1.0 feed RSS 2.0 feed   Blog Painless OAuth with PHP