Recently I’ve been working a lot on trying to get OAuth2 support into beta 4 of Zend Framework 2, and there were a few challenges. Allowing the client to consume the variety of providers out there proved to be the first. There have been several drafts of the OAuth2 specification, and providers have implemented a variety of the drafts. As each of the drafts have subtle differences, the client needs to be able to have a default configuration that can be over-ridden on a per-provider basis.
OAuth 2 is a 2-step process that I like to think of in 4-steps, that allows an application to retrieve an access token that can be used to request further information on the logged in user from the API:
- Client sends request to the OAuth2 server containing the unique application identifier and the scope of access the application requires.
- The server responds with an encrypted response containing a time-sensitive code that can be exchanged for an access token.
- Client decrypts the code, and send it back to the server.
- Server responds with an access_code and it’s expiry time.
The solution we came up with was to have an options class for each stage of the authentication process that contains the name of each parameter, plus a default value. Individual vendor configs can overwrite both the key name, and it’s value, or for more specific providers it can be set at run-time (or new a vendor config file can be created). The idea is to support out-of-the-box as many common vendors as possible, so that Mr End User can simply do:
$OAuth2 = new Client(new ClientOptionsVendorGoogle()); $token = $OAuth2->getAccessToken();
Overwriting certain parameters for a specific implementation is also very easy. A good example is Facebook. The specification dictates that the stage 2 response returns an access code, and the number of seconds before that code will expire. The spec also says this parameter should be named “expires_in”, however when Facebook coded their implementation, the field was named “expires”. Using the simple overloading method, we can easily make this change in the vendor specific config:
$this->vendorOptions = new VendorOptions(array( 'authEntryUri' => 'https://www.facebook.com/dialog/oauth', 'tokenEntryUri' => 'https://graph.facebook.com/oauth/access_token', 'responseFormat' => 'urlencode', 'headers' => array(), )); $this->stage2Response->expiresIn->accessKey = 'expires';
We set up some vendor specific uris, and then tell the config that the stage 2 response “expires_in” key is actually named “expires”.
I’m pretty excited about how this has turned out, now all we need to do is to come to some kind of concencious on where in the framework this code will live. For more discussion, join the action in #zftalk.2 on Freenode.