2
0

Zend_Oauth-GettingStarted.xml 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect2 id="zend.oauth.introduction.getting-started">
  4. <title>Getting Started</title>
  5. <para>
  6. With the OAuth protocol explained, let's show a simple example of it with
  7. source code. Our new Consumer will be handling Twitter Status submissions.
  8. To do so, it will need to be registered with Twitter in order to receive
  9. an OAuth Consumer Key and Consumer Secret. This are utilised to obtain
  10. an Access Token before we use the Twitter <acronym>API</acronym> to post a status message.
  11. </para>
  12. <para>
  13. Assuming we have obtained a key and secret, we can start the OAuth workflow
  14. by setting up a <classname>Zend_Oauth_Consumer</classname> instance as
  15. follows passing it a configuration (either an array or <classname>Zend_Config</classname>
  16. object).
  17. </para>
  18. <programlisting language="php"><![CDATA[
  19. $config = array(
  20. 'callbackUrl' => 'http://example.com/callback.php',
  21. 'siteUrl' => 'http://twitter.com/oauth',
  22. 'consumerKey' => 'gg3DsFTW9OU9eWPnbuPzQ',
  23. 'consumerSecret' => 'tFB0fyWLSMf74lkEu9FTyoHXcazOWpbrAjTCCK48A'
  24. );
  25. $consumer = new Zend_Oauth_Consumer($config);
  26. ]]></programlisting>
  27. <para>
  28. The callbackUrl is the URI we want Twitter to request from our server
  29. when sending information. We'll look at this later. The siteUrl is the
  30. base URI of Twitter's OAuth <acronym>API</acronym> endpoints. The full list of endpoints
  31. include http://twitter.com/oauth/request_token, http://twitter.com/oauth/access_token,
  32. and http://twitter.com/oauth/authorize. The base siteUrl utilises a convention
  33. which maps to these three OAuth endpoints (as standard) for requesting a
  34. request token, access token or authorization. If the actual endpoints of
  35. any service differ from the standard set, these three URIs can be separately
  36. set using the methods <methodname>setRequestTokenUrl()</methodname>,
  37. <methodname>setAccessTokenUrl()</methodname>,
  38. and <methodname>setAuthorizeUrl()</methodname> or the configuration fields requestTokenUrl,
  39. accessTokenUrl and authorizeUrl.
  40. </para>
  41. <para>
  42. The consumerKey and consumerSecret are retrieved from Twitter when your
  43. application is registered for OAuth access. These also apply to any OAuth
  44. enabled service, so each one will provide a key and secret for your
  45. application.
  46. </para>
  47. <para>
  48. All of these configuration options may be set using method calls simply
  49. by converting from, e.g. callbackUrl to setCallbackUrl().
  50. </para>
  51. <para>
  52. In addition, you should note several other configuration values not
  53. explicitly used: requestMethod and requestScheme. By default,
  54. <classname>Zend_Oauth_Consumer</classname> sends requests as POST (except for a
  55. redirect which uses <constant>GET</constant>). The customised client (see later) also
  56. includes its authorization by way of a header. Some services may, at their discretion,
  57. require alternatives. You can reset the requestMethod (which defaults
  58. to Zend_Oauth::POST) to Zend_Oauth::GET, for example, and reset the
  59. requestScheme from its default of Zend_Oauth::REQUEST_SCHEME_HEADER to one
  60. of Zend_Oauth::REQUEST_SCHEME_POSTBODY or
  61. Zend_Oauth::REQUEST_SCHEME_QUERYSTRING. Typically the defaults should work
  62. fine apart from some exceptional cases. Please refer to the service provider's
  63. documentation for more details.
  64. </para>
  65. <para>
  66. The second area of customisation is how <acronym>HMAC</acronym> operates
  67. when calculating/comparing them for all requests. This is configured using
  68. the signatureMethod configuration field or <methodname>setSignatureMethod()
  69. </methodname>. By default this is HMAC-SHA1. You can set it also to a provider's
  70. preferred method including RSA-SHA1. For RSA-SHA1, you should also configure
  71. RSA private and public keys via the rsaPrivateKey and rsaPublicKey configuration
  72. fields or the <methodname>setRsaPrivateKey()</methodname> and
  73. <methodname>setRsaPublicKey()</methodname> methods.
  74. </para>
  75. <para>
  76. The first part of the OAuth workflow is obtaining a request token. This
  77. is accomplished using:
  78. </para>
  79. <programlisting language="php"><![CDATA[
  80. $config = array(
  81. 'callbackUrl' => 'http://example.com/callback.php',
  82. 'siteUrl' => 'http://twitter.com/oauth',
  83. 'consumerKey' => 'gg3DsFTW9OU9eWPnbuPzQ',
  84. 'consumerSecret' => 'tFB0fyWLSMf74lkEu9FTyoHXcazOWpbrAjTCCK48A'
  85. );
  86. $consumer = new Zend_Oauth_Consumer($config);
  87. // fetch a request token
  88. $token = $consumer->getRequestToken();
  89. ]]></programlisting>
  90. <para>
  91. The new request token (an instance of <classname>Zend_Oauth_Token_Request
  92. </classname>) is unauthorized. In order to exchange it for an authorized
  93. token with which we can access the Twitter <acronym>API</acronym>, we need the user to
  94. authorize it. We accomplish this by redirecting the user to Twitter's authorize endpoint
  95. via:
  96. </para>
  97. <programlisting language="php"><![CDATA[
  98. $config = array(
  99. 'callbackUrl' => 'http://example.com/callback.php',
  100. 'siteUrl' => 'http://twitter.com/oauth',
  101. 'consumerKey' => 'gg3DsFTW9OU9eWPnbuPzQ',
  102. 'consumerSecret' => 'tFB0fyWLSMf74lkEu9FTyoHXcazOWpbrAjTCCK48A'
  103. );
  104. $consumer = new Zend_Oauth_Consumer($config);
  105. // fetch a request token
  106. $token = $consumer->getRequestToken();
  107. // persist the token to storage
  108. $_SESSION['TWITTER_REQUEST_TOKEN'] = serialize($token);
  109. // redirect the user
  110. $consumer->redirect();
  111. ]]></programlisting>
  112. <para>
  113. The user will now be redirected to Twitter. They will be asked to authorize
  114. the request token attached to the redirect URI's query string. Assuming they
  115. agree, and complete the authorization, they will be again redirected, this
  116. time to our Callback URL as previously set (note that the callback URL is
  117. also registered with Twitter when we registered our application).
  118. </para>
  119. <para>
  120. Before redirecting the user, we should persist the request token to storage.
  121. For simplicity I'm just using the user's session, but you can easily use a
  122. database for the same purpose, so long as you tie the request token to the
  123. current user so it can be retrieved when they return to our application.
  124. </para>
  125. <para>
  126. The redirect URI from Twitter will contain an authorized Access Token. We
  127. can include code to parse out this access token as follows - this source
  128. code would exist within the executed code of our callback URI. Once parsed
  129. we can discard the previous request token, and instead persist the access
  130. token for future use with the Twitter <acronym>API</acronym>. Again, we're simply persisting
  131. to the user session, but in reality an access token can have a long lifetime
  132. so it should really be stored to a database.
  133. </para>
  134. <programlisting language="php"><![CDATA[
  135. $config = array(
  136. 'callbackUrl' => 'http://example.com/callback.php',
  137. 'siteUrl' => 'http://twitter.com/oauth',
  138. 'consumerKey' => 'gg3DsFTW9OU9eWPnbuPzQ',
  139. 'consumerSecret' => 'tFB0fyWLSMf74lkEu9FTyoHXcazOWpbrAjTCCK48A'
  140. );
  141. $consumer = new Zend_Oauth_Consumer($config);
  142. if (!empty($_GET) && isset($_SESSION['TWITTER_REQUEST_TOKEN'])) {
  143. $token = $consumer->getAccessToken(
  144. $_GET,
  145. unserialize($_SESSION['TWITTER_REQUEST_TOKEN'])
  146. );
  147. $_SESSION['TWITTER_ACCESS_TOKEN'] = serialize($token);
  148. // Now that we have an Access Token, we can discard the Request Token
  149. $_SESSION['TWITTER_REQUEST_TOKEN'] = null;
  150. } else {
  151. // Mistaken request? Some malfeasant trying something?
  152. exit('Invalid callback request. Oops. Sorry.');
  153. }
  154. ]]></programlisting>
  155. <para>
  156. Success! We have an authorized access token - so it's time to actually
  157. use the Twitter <acronym>API</acronym>. Since the access token must be included with every
  158. single <acronym>API</acronym> request, <classname>Zend_Oauth_Consumer</classname> offers a
  159. ready-to-go <acronym>HTTP</acronym> client (a subclass of
  160. <classname>Zend_Http_Client</classname>) to use either by itself or by passing it as a
  161. custom <acronym>HTTP</acronym> Client to another library or
  162. component. Here's an example of using it standalone. This can be done
  163. from anywhere in your application, so long as you can access the OAuth
  164. configuration and retrieve the final authorized access token.
  165. </para>
  166. <programlisting language="php"><![CDATA[
  167. $config = array(
  168. 'callbackUrl' => 'http://example.com/callback.php',
  169. 'siteUrl' => 'http://twitter.com/oauth',
  170. 'consumerKey' => 'gg3DsFTW9OU9eWPnbuPzQ',
  171. 'consumerSecret' => 'tFB0fyWLSMf74lkEu9FTyoHXcazOWpbrAjTCCK48A'
  172. );
  173. $statusMessage = 'I\'m posting to Twitter using Zend_Oauth!';
  174. $token = unserialize($_SESSION['TWITTER_ACCESS_TOKEN']);
  175. $client = $token->getHttpClient($configuration);
  176. $client->setUri('http://twitter.com/statuses/update.json');
  177. $client->setMethod(Zend_Http_Client::POST);
  178. $client->setParameterPost('status', $statusMessage);
  179. $response = $client->request();
  180. $data = Zend_Json::decode($response->getBody());
  181. $result = $response->getBody();
  182. if (isset($data->text)) {
  183. $result = 'true';
  184. }
  185. echo $result;
  186. ]]></programlisting>
  187. <para>
  188. As a note on the customised client, this can be passed to most
  189. Zend Framework service or other classes using <classname>Zend_Http_Client
  190. </classname> displacing the default client they would otherwise use.
  191. </para>
  192. </sect2>