Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_Oauth Component Proposal

Proposed Component Name Zend_Oauth
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend_Oauth
Proposers Pádraic Brady
Matthew Weier O'Phinney, Zend liaison
Revision 1.0.1 - 1 July 2008 (wiki revision: 16)

Table of Contents

1. Overview

The OAuth protocol was published in its final Specification 1.0 on 4 December 2007. It is a protocol allowing websites, web applications or desktop applications to access Service Resources via an API without requiring Users to disclose their credentials. It is an open and decentralised protocol.

A simple use case would be Twitter. At present, Twitter applications such as Spaz.air or Twitterer usually require a User's login username and password (their credentials) in order to access the timeline of other Users they are following or send updates (tweets). This raises a risk that such applications may use those credentials to change the User's password, send "tweets" without their permission, or other unauthorised actions allowable through authenticating with a username/password.

Implementing OAuth, such an application would be able to perform limited authorised actions without requiring Users to disclose their credentials. In effect, this is similar to establishing an API Key and indeed OAuth builds upon existing standards. But the net effect is one of limited access, with OAuth external applications are given defined limited authorisation which can be limited according to function, resource or timeframe.

OAuth is therefore perfect also in situations where a Service Provider is not aware of a User's credentials, as is the case when a Provider implements OpenID. In OpenID, credentials are centralised to a single OpenID Provider and implementing Consumers will require an alternate means of allowing authenticated Users to access their Service Resources via an API. OAuth is not an OpenID extension, but does complement it.

The implementation of OAuth is quite flexible, and the specification is marked "Core" to highlight the ability of Service Providers to create extensions and utilise more secure or different means of exchanging messages.

Future Developments

It's worth noting that OAuth is not a static protocol. Discussions for an OAuth Core 1.1 Specification have been underway for some time and recently entered public comment stage. These changes will be rolled into future Zend_Oauth iterations as a matter of course. The expected changes include:

  1. Adoption of standard error codes and human readable error messages in responses (required for simple interoperability across all Service Providers)
  2. Adoption of a Service Provider Discovery protocol similar to OpenID (i.e. XRDS-Simple and Yadis)
  3. Inclusion of language determination
  4. Clarification of scaling and security concerns

In addition the Core 1.0 Specification may be extended through the use of Extensions. Several draft Extenstion Specs are already doing the rounds:

  1. OAuth Session Extension Draft 0.1
  2. OAuth Discovery 1.0 Draft 2

Also, while waiting for Zend_Service_Yadis approval there is already need for a major revision and updated testing suite to support new specification drafts:

2. References

See above for copies of related Specifications and Draft Specifications.

3. Component Requirements, Constraints, and Acceptance Criteria

  • This component will implement the entirety of the OAuth Core 1.0 Final specification without exceptions
  • This component will implement a fully featured Consumer
  • This component will implement a fully featured Provider/Server
  • This component will implement the most recent draft of the OAuth Discovery 1.0 Draft Specification

4. Dependencies on Other Framework Components

Zend_Http_Client
Zend_Crypt_Hmac (Incubator)
Zend_Crypt_Rsa (Incubator)
Zend_Service_Yadis (Incubator)
Zend_Exception
Zend_Uri

5. Theory of Operation

Hypothetical Example:

A Service Provider engaged in allowing User's to answer one question "What are you NOT doing?" has determined that requiring User credentials to access their Web Service API is unnecessarily risky. To improve User security, ease development by adopting an open standard, and allow for future OpenID adoption, they determine to implement OAuth 1.0.

The Service Provider provides to Developers details of how to register for a Consumer Key and Consumer Secret, and declares several new URLs including:

Request Token URL:
https://example.com/request_token, using HTTP POST
User Authorization URL:
http://example.com/authorize, using HTTP Authorize Header
Access Token URL:
https://example.com/access_token, using HTTP POST

The Service Provider provides support for HMAC-SHA1 message signatures. RSA-SHA1 is also a possible alternative (though not for this example! ).

1. Obtaining an initial Request Token (Requesting Approval)

Joe Bloggs, a User, visits a third-party web application from which he wishes to view and post new updates to the Service Provider. The application tries to access the User's posts but receives a HTTP 401 Unauthorized header including the following response header:

WWW-Authenticate: OAuth realm="http://example.com/authorize"

The application sends back a HTTP POST request:

https://example.com/request_token?oauth_consumer_key=dpf43f3p2l4k3l03
&oauth_signature_method=PLAINTEXT&oauth_signature=kd94hf93k423kf44%26
&oauth_timestamp=1191242090&oauth_nonce=hsu94j3884jdopsl&oauth_version=1.0

The Service Provider verifies the oauth_signature value and sends back an unauthorised (requires User authorisation) Request Token in the response body:

oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03

2. Obtaining User Authorisation of Request (Approve Request)

The application at this point redirects the User to the Service Provider Authorization URL so that Joe can approve the application's access to the Service Provider.

http://example.com/authorize?oauth_token=hh5s93j4hdidpola
&oauth_callback=http%3A%2f%2fprinter.example.com%2Frequest_token_ready

Joe will log in using either his credentials, or via OpenID. He may then approve the application's access, set limits, and perhaps even time the access to a specific timeframe. Once approved, the Service Provider will redirect back to the Consuming web application with:

3. Obtaining an Access Token on foot of an approved Request Token (Gaining Access)

Now that the web application is approved for access, they can request an Access Token to replace the Request Token:

https://example.com/access_token?oauth_consumer_key=dpf43f3p2l4k3l03
&oauth_token=hh5s93j4hdidpola&oauth_signature_method=PLAINTEXT
&oauth_signature=kd94hf93k423kf44%26hdhd0244k9j7ao03&oauth_timestamp=1191242092
&oauth_nonce=dji430splmx33448&oauth_version=1.0

The Service Provider will check the signature, and reply with an Access Token in the response body:

oauth_token=nnch734d00sl2jdk&oauth_token_secret=pfkkdhi9sl3r4s00

The Consuming application is now ready to make authorised requests of the Web Service API. If the Web Service API URL is unsecured (not HTTPS) then subsequent requests must be signed using HMAC-SHA1 to protect the Access Token from being intercepted and being used by an unauthorised party.

Security Notes: PLAINTEXT style requests are intended only for use across a secured connection. Otherwise a cryptographic method such as Diffie-Hellman may be utilised (unspecified by OAuth 1.0 of course). Consumer Access Tokens should not be used to assume a Consumer is a User. Access Tokens should allow only limited authorised actions. Phishing remains an issue. Users must be careful that Service Provider URLs they are redirected to for entering credentials are authenticated.

6. Milestones / Tasks

  • Milestone 1: Write unit tests capturing the agreed interface and behaviour
  • Milestone 2: Write the code required to pass all unit tests
  • Milestone 3: Write integration tests to cover various edge cases
  • Milestone 4: Verify that code operates under PHP 5.3 (an Openssl API issue)
  • Milestone 5: Complete documentation

7. Class Index

  • Zend_Oauth
  • Zend_Oauth_Consumer
  • Zend_Oauth_Server
  • Zend_Oauth_Http
  • Zend_Oauth_Http_RequestToken
  • Zend_Oauth_Http_AccessToken
  • Zend_Oauth_Http_UserAuthorisation
  • Zend_Oauth_Http_Utility
  • Zend_Oauth_Client
  • Zend_Oauth_Token
  • Zend_Oauth_Token_Request
  • Zend_Oauth_Token_Access
  • Zend_Oauth_Token_Access
  • Zend_Oauth_Exception

Others may be determined during development

8. Use Cases

Use cases are currently being drafted.

UC-01

A start to finish example using the Ma.gnolia API:

UC-02

A start to finish example using the Google Data Contacts API:

UC-03

Options may be set using a typical Options array, in the future using Zend_Config, and individually using publicly accessible mutators and accessors:

9. Class Skeletons

Please refer to ongoing development in my subversion repository

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
proposal proposal Delete
zend_webservices zend_webservices Delete
oauth oauth Delete
authorization authorization Delete
api api Delete
openid openid Delete
service service Delete
identity identity Delete
claims claims Delete
auth auth Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Oct 16, 2007

    <p>Is this supposed to be an OAuth consumer, provider, or both?</p>

    <p>Considering that I could see use for both, would it make more sense to break this into two seperate modules, i.e., Zend_OAuth_Provider and Zend_OAuth_Consumer?</p>

    <p>Also, right now this mostly just duplicates the information in the OAuth spec. There should probably be a little bit more information as to what the public interface is going to look like.</p>

  2. Oct 16, 2007

    <p>One more thing:</p>

    <p>Zend_OAuth should be Zend_Oauth. According to the <ac:link><ri:page ri:content-title="PHP Coding Standard (draft)" ri:space-key="ZFDEV" /><ac:link-body>style guide</ac:link-body></ac:link>:</p>

    <blockquote><p>If a class name is comprised of more than one word, the first letter of each new word must be capitalized. Successive capitalized letters are not allowed; e.g., a class "Zend_PDF" is not allowed, while "Zend_Pdf" is acceptable.</p></blockquote>

    <p><em>This and my previous comment are regarding version 0.9 (r5) of this draft.</em></p>

  3. Oct 17, 2007

    <p>OAuth is two words pulled together in abbreviated form - if the naming is not acceptable I'll switch to Oauth of course. I have no concern over naming.<br />
    At present the component is a single namespace, so eventually there would be Zend_Service_OAuth_Consumer. I'm not sure whether a Zend_Oauth would be allowed but I'll grab a Zender and check. I may take you up though and make it clear this will start with a Consumer first - and break it into two proposals.</p>

    <p>Yes, it does duplicate the information from the spec. There's a good reason for this - unlike OpenID the Specification is only at the start of an implementation phase and was publically released on 3rd October so documentation off the private mailing list is extremely light. I literally saw the very first Twitter exchange work days ago and it was deadly simple in PHP <ac:emoticon ac:name="wink" />. So the only reference (which I omitted for some reason - sorry) is the Specification itself. There's no other full implementation just yet to reference. I'll update the text over time before enters the review stage.</p>

    <p>On a public interface, I'm working on one for the Consumer. I explained this a few times to folk before - I apply XP and TDD when developing (most of the time when not in a huge hurry <ac:emoticon ac:name="smile" />) so I literally do not know the API until I commence development. I'm presently writing a set of user stories so I can get some Acceptance Tests specified - should get a preliminary idea of an API from there. Either way, prior to applying BDD I'll have no idea of what classes will be needed other than a basic public API for a theoretical Consumer class (which may even die after the first few tests/specs are written <ac:emoticon ac:name="wink" />) - so class skeletons are out of the question. I'll try and get the basic API that may be implemented up soon - at least give readers of taste of how it works.</p>

    <p>One other comment - at the moment there are a few points I haven't referenced which aren't in the Specification. If you dig around for OAuth Extensions there is a discussion right now as to how to handle message signing (on another closed list unfortunately - applying for membership isn't difficult). For example the Spec mentions PLAINTEXT, RSA and HMAC-SHA1 but doesn't specify anything further about recommended RSA or handling signature type variances between the Consumer and Provider. It literally leaves it wide open for a Service Provider to work out.</p>

    <p>I've suggested HMAC-SHA256 as a definite option on the list (others have also) - we already have a full HMAC implementation in the ZF Incubator from my OpenID work (see Zend_Crypt) - which would provide a HMAC signature based on at least one hashing type without a known collision as supported in a Spec Extension.</p>

    <p>Maybe I should just copy and past all this to Overview? <ac:emoticon ac:name="wink" /></p>

    1. Oct 20, 2007

      <p>Sounds good. I look forwarding to seeing what this will look like once you start to get things implemented.</p>

      <p>Oh, and regarding the naming thing, I personally like Zend_OAuth better than Zend_Oauth, but I didn't write the style guide. <ac:emoticon ac:name="smile" /> The Google Data module is named Zend_Gdata, so I guess that could be considered precident. Definitely check with someone from Zend to be sure.</p>

  4. May 14, 2008

    <p>Paddy, what is the latest on this proposal? Are you going to actively work on it soon, or should we move it to the 'archived' section for now?</p>

    1. Jun 17, 2008

      <p>A month later...<ac:emoticon ac:name="wink" />. Must not have this page on my watchlist...</p>

      <p>The source code is now in active development. I intend updating the proposal text, making reference to the subversion location, and pushing it through the proposal machine. Hope to have a relatively basic Consumer up and running before the week is out. The code, for the moment, will assume the presence of a Zend_Crypt_Rsa component which is entirely optional (since it's under a separate proposal altogether so I don't expect to rely on that unless its passed).</p>

      <p>Most of the current work is simply getting stuff up and running so I can see where the code might end up before booting PHPUnit into action for TDD.</p>

  5. Jun 24, 2008

    <p>I added a single complete Use Case using the Ma.gnolia API. This is also pulled from my main acceptance test. The Http Client can be considered dodgy <ac:emoticon ac:name="wink" />. It's not tested since it's a subclass of Zend_Http_Client and the changes are speculative. They do work so long as you stick to POST.</p>

    <p>The previous source code in the repository has also been heavily refactored. A storage medium for tokens is being looked into as the next feature iteration.</p>

    <p>If you're reading this, please do comment!</p>

  6. Jul 01, 2008

    <p>Paddy, a few comments and questions.</p>

    <p>First, my big question is whether you intend to implement a Provider as part of this proposal, or if that will be a separate effort. If it will be a separate effort, I encourage you to rename this proposal to Zend_Oauth_Consumer, and indicate that a Provider will be proposed later.</p>

    <p>Second, does the implementation include mutators and accessors for all options that can be passed to the constructor? If not, I'd recommend allowing this use case.</p>

    <p>Third, I'd recommend both setOptions() and setConfig() methods, the former for passing an array of options, the second for passing a Zend_Config object; the constructor should also allow passing a Zend_Config object.</p>

  7. Jul 01, 2008

    <p>Hi Matthew,</p>

    <p>I'll clarify the proposal for my answers during tomorrow.</p>

    <p>It is intended the develop a Provider/Server, and indeed the source code for one is sitting around awaiting a commit. For the moment it's been completing and refactoring the Consumer first, but as the proposal states the objective is to implement the entire specification - no exceptions. And also the top 3 most common extensions - which though it appears selective is actually because the same top 3 are due for attention in the new OAuth 2008.1 spec discussions.</p>

    <p>There's already a setOptions() method, and I'll add a setConfig() one a bit later - think it's a commented todo in the Consumer class. All options also have distinct setters and getters with some sanity checking. Since that interface is reusable to encourage decoupling of options/config from the Consumer class it has a separate Interface defined in Zend_Oauth_Config_Interface. The same interface will turn up in the Provider, and is already part of the Oauth_Client class.</p>

    <p>Any other questions, feel free to throw them my way <ac:emoticon ac:name="smile" />.</p>

  8. Jul 01, 2008

    <p>Proposal edited - added to tasks/objectives a clarification the proposal will develop both Server and Consumer. Also added a small use case clarifying that mutators/accessors do exist for all options.</p>

  9. Jul 10, 2008

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Comments</ac:parameter><ac:rich-text-body>
    <p>This proposal is accepted as-is for development in the standard/incubator.</p></ac:rich-text-body></ac:macro>

  10. Nov 26, 2008

    <p>What is the status of this proposal? The SVN repository links are no longer valid. Has the source moved? If so, where?</p>

    1. Nov 26, 2008

      <p>I'm not sure what the state of the proposal is, but the ZF SVN server underwent a reorganization a few months ago.</p>

      <p>The incubator now lives at:</p>

      <p><a class="external-link" href="http://framework.zend.com/svn/framework/standard/incubator">http://framework.zend.com/svn/framework/standard/incubator</a></p>

      <p>Which means Zend_Oauth lives at:</p>

      <p><a class="external-link" href="http://framework.zend.com/svn/framework/standard/incubator/library/Zend/Oauth">http://framework.zend.com/svn/framework/standard/incubator/library/Zend/Oauth</a></p>

  11. Mar 18, 2009

    <p>Paddy, what is the status of this proposal?</p>

  12. Apr 16, 2009

    <p>I'm also curious as to the status of this proposal.</p>

    1. Apr 16, 2009

      <p>Seconded <ac:emoticon ac:name="smile" /></p>

  13. May 04, 2009

    <p>I had to add the following patch to Oauth/Client.php when I've used the svn copy of Oauth with the subclass of Zend_Service_Twitter. It seems without this patch the client sends wrong POST and GET parameters to the REST api. Please check my code and apply the patch if it's acceptable.<br />
    Patch url: <a class="external-link" href="http://blog.linuxforge.hu/UserFiles/File/oauth_parameter_fix.patch">http://blog.linuxforge.hu/UserFiles/File/oauth_parameter_fix.patch</a></p>

  14. Jul 02, 2009

    <p>I would also love to know how this proposal is coming along, any updates would be great.</p>

    <p>This seems like a great way of working with Twitter.</p>

    <p>Balazs: Is your extension to Zend_Service_Twitter publically available?</p>

  15. Jul 03, 2009

    <p>Here is a patch that allows an object that implements Zend_Oauth_Config_Interface to be passed to the Zend_Oauth_Consumer constructor.</p>

    <p><a class="external-link" href="http://files.getdropbox.com/u/41936/adamcharnock-oauth.patch">http://files.getdropbox.com/u/41936/adamcharnock-oauth.patch</a></p>

    <p>I found this useful because I needed to extend Zend_Oauth_Config to support additional config parameters. In this case, I wanted to store the URL for the 'Sign in with Twitter' image (which is read in from a config file)</p>

  16. Jul 04, 2009

    <p>This component will be moving forward as soon as possible. I'm currently completing Zend_Feed_Reader for a 1.9 release. OAuth is next on the list with the same urgency <ac:emoticon ac:name="smile" />. My kindest wishes to those who have submitted patches here!</p>

    1. Dec 04, 2009

      <p>Is it possible to use Zend_OAuth from the incubator in the actual state? Are there plans for implementing it in 1.10? I've looked at Fisheye and there was the last commit at 06 October 2009.</p>

  17. Oct 08, 2009

    <p>Any news on this one? </p>

  18. Nov 24, 2009

    <p>Hi,</p>

    <p>Thanks for this component. The consumer part rocks. I tried it with twitter API and it works.</p>

    <p>But (there is always a but),</p>

    <p>I tried it with the new linkedin API wich implements OAuth1.0a and there is an issue. To avoid Man in the middle attack, they associate the callback url with the request token, during its creation. But when the Zend Consumer calls authorize URL with a callback_url parameter, the server rejects the API call.</p>

    <p>If I remove the callback url parameter from Zend_Oauth_Http_UserAuthorisation line 64, it works with linkedIn. But it will not work anymore with Oauth 1.0 servers or even with Oauth 1.0a server which are not so "strict"</p>

    <p>Maybe we could enable the Consumer component to understand the 1.0a version set in the constructor or in the config file.</p>

    <p>What do you think ?</p>

    1. Dec 05, 2009

      <p>Alexandre, can you please create an issue for that? So that the maintainer can tracks this issue and working on a bugfix?</p>

      <p><a class="external-link" href="http://framework.zend.com/issues/">http://framework.zend.com/issues/</a></p>

  19. Dec 08, 2009

    <p>Out of curiosity, but would it be possible to develop an Zend_Auth_Adapter using Zend_Oauth?</p>

    1. Dec 08, 2009

      <p>Oauth is not an authentication Protocol like Open ID or ldap. This is a authorization protocol used to exchange trusted tokens between applications.</p>

      1. Dec 09, 2009

        <p>Oh, my bad. I've mixed to concepts which are independent.</p>

  20. Feb 22, 2011

    <p>Zend_Oauth is released into the stable branch. Maybe we can archive this proposal <ac:emoticon ac:name="smile" /></p>