remove old readme
[atutor.git] / docs / mods / _standard / social / lib / Shindig / ATutorOAuthLookupService.php
1 <?php
2 /***********************************************************************/
3 /* ATutor                                                                                                                          */
4 /***********************************************************************/
5 /* Copyright (c) 2002-2010                                             */
6 /* Inclusive Design Institute                                          */
7 /* http://atutor.ca                                                                                                        */
8 /*                                                                                                                                         */
9 /* This program is free software. You can redistribute it and/or           */
10 /* modify it under the terms of the GNU General Public License             */
11 /* as published by the Free Software Foundation.                                           */
12 /***********************************************************************/
13 // $Id$
14
15 /**
16  * ATutor's implementation of OAuthLookupService, which does all the heavy lifting for the oauth protocol handling
17  * and authentication matching
18  * Refer to shindig/php/src/common/OAuthLookUpService.php
19  */
20 class ATutorOAuthLookupService extends OAuthLookupService {
21
22   /**
23    * ATutor's implementation of the OAuth Lookup service. ATutor supports all currently existing forms of
24    * OAuth signatures: 3 legged, 2 legged and body_hash's
25    *
26    * @param RequestItem $oauthRequest
27    * @param string $appUrl
28    * @param string $userId
29    * @return SecurityToken or null
30    */
31   public function getSecurityToken($oauthRequest, $appUrl, $userId) {
32     try {
33       // Incomming requests with a POST body can either have an oauth_body_hash, or include the post body in the main oauth_signature; Also for either of these to be valid
34       // we need to make sure it has a proper the content-type; So the below checks if it's a post, if so if the content-type is supported, and if so deals with the 2
35       // post body signature styles
36       $includeRawPost = false;
37       if (isset($GLOBALS['HTTP_RAW_POST_DATA']) && ! empty($GLOBALS['HTTP_RAW_POST_DATA'])) {
38                   if (isset($_GET['oauth_body_hash'])) {
39                         // this request uses the oauth_body_hash spec extension. Check the body hash and if it fails return 'null' (oauth signature failure)
40                         // otherwise continue on to the regular oauth signature verification, without including the post body in the main oauth_signature calculation
41                         if (! $this->verifyBodyHash($GLOBALS['HTTP_RAW_POST_DATA'], $_GET['oauth_body_hash'])) {
42                           return null;
43                         }
44                   } else {
45                         // use the (somewhat oauth spec invalid) raw post body in the main oauth hash calculation
46                         $includeRawPost = $GLOBALS['HTTP_RAW_POST_DATA'];
47                   }
48       }
49       $dataStore = new ATutorOAuthDataStore();
50       if ($includeRawPost) {
51         // if $includeRawPost has been set above, we need to include the post body in the main oauth_signature
52         $oauthRequest->set_parameter($includeRawPost, '');
53       }
54       if (! isset($oauthRequest->parameters['oauth_token'])) {
55         // No oauth_token means this is a 2 legged OAuth request
56         $ret = $this->verify2LeggedOAuth($oauthRequest, $userId, $appUrl, $dataStore);
57       } else {
58         // Otherwise it's a clasic 3 legged oauth request
59         $ret = $this->verify3LeggedOAuth($oauthRequest, $userId, $appUrl, $dataStore);
60       }
61       if ($includeRawPost) {
62         unset($oauthRequest->parameters[$includeRawPost]);
63       }
64       return $ret;
65     } catch (OAuthException $e) {
66       return null;
67     }
68   }
69
70   /**
71    * Verfies the oauth_body_hash signature, for more information on this oauth spec extension see:
72    * http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html
73    */
74   private function verifyBodyHash($postBody, $oauthBodyHash) {
75     return base64_encode(sha1($postBody, true)) == $oauthBodyHash;
76   }
77
78   /**
79    * Verfies a 2 legged OAuth signature. 2 legged OAuth means the security context is of the application,
80    * and no specific user is associated with it. Most of the logic is done manually and not through the OAuth
81    * library, since it has no knowledge of- / support for 2 legged OAuth.
82    */
83   private function verify2LeggedOAuth($oauthRequest, $userId, $appUrl, $dataStore) {
84     $consumerToken = $dataStore->lookup_consumer($oauthRequest->parameters['oauth_consumer_key']);
85     $signature_method = new OAuthSignatureMethod_HMAC_SHA1();
86     $signature_valid = $signature_method->check_signature($oauthRequest, $consumerToken, null, $_GET["oauth_signature"]);
87     if (! $signature_valid) {
88       // signature did not check out, abort
89       return null;
90     }
91     return new OAuthSecurityToken($userId, $appUrl, $dataStore->get_app_id($consumerToken), "atutor");
92   }
93
94   /**
95    * The 'clasic' 3 legged OAuth, where the user went through the OAuth dance and granted the remote app
96    * access to his/her data.
97    */
98   private function verify3LeggedOAuth($oauthRequest, $userId, $appUrl, $dataStore) {
99     $server = new OAuthServer($dataStore);
100     $server->add_signature_method(new OAuthSignatureMethod_HMAC_SHA1());
101     $server->add_signature_method(new OAuthSignatureMethod_PLAINTEXT());
102     list($consumer, $token) = $server->verify_request($oauthRequest);
103     $oauthUserId = $dataStore->get_user_id($token);
104     if ($userId && $oauthUserId && $oauthUserId != $userId) {
105       return null; // xoauth_requestor_id was provided, but does not match oauth token -> fail
106     } else {
107       $userId = $oauthUserId; // use userId from oauth token
108       return new OAuthSecurityToken($userId, $appUrl, $dataStore->get_app_id($consumer), "atutor");
109     }
110   }
111 }