Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
1 <?php 2 3 namespace IMSGlobal\LTI\OAuth; 4 5 /** 6 * Class to represent an %OAuth Server 7 * 8 * @copyright Andy Smith 9 * @version 2008-08-04 10 * @license https://opensource.org/licenses/MIT The MIT License 11 */ 12 #[\AllowDynamicProperties] 13 class OAuthServer { 14 15 protected $timestamp_threshold = 300; // in seconds, five minutes 16 protected $version = '1.0'; // hi blaine 17 protected $signature_methods = array(); 18 19 protected $data_store; 20 21 function __construct($data_store) { 22 $this->data_store = $data_store; 23 } 24 25 public function add_signature_method($signature_method) { 26 $this->signature_methods[$signature_method->get_name()] = $signature_method; 27 } 28 29 // high level functions 30 31 /** 32 * process a request_token request 33 * returns the request token on success 34 */ 35 public function fetch_request_token(&$request) { 36 37 $this->get_version($request); 38 39 $consumer = $this->get_consumer($request); 40 41 // no token required for the initial token request 42 $token = NULL; 43 44 $this->check_signature($request, $consumer, $token); 45 46 // Rev A change 47 $callback = $request->get_parameter('oauth_callback'); 48 $new_token = $this->data_store->new_request_token($consumer, $callback); 49 50 return $new_token; 51 52 } 53 54 /** 55 * process an access_token request 56 * returns the access token on success 57 */ 58 public function fetch_access_token(&$request) { 59 60 $this->get_version($request); 61 62 $consumer = $this->get_consumer($request); 63 64 // requires authorized request token 65 $token = $this->get_token($request, $consumer, "request"); 66 67 $this->check_signature($request, $consumer, $token); 68 69 // Rev A change 70 $verifier = $request->get_parameter('oauth_verifier'); 71 $new_token = $this->data_store->new_access_token($token, $consumer, $verifier); 72 73 return $new_token; 74 75 } 76 77 /** 78 * verify an api call, checks all the parameters 79 */ 80 public function verify_request(&$request) { 81 82 $this->get_version($request); 83 $consumer = $this->get_consumer($request); 84 $token = $this->get_token($request, $consumer, "access"); 85 $this->check_signature($request, $consumer, $token); 86 87 return array($consumer, $token); 88 89 } 90 91 // Internals from here 92 /** 93 * version 1 94 */ 95 private function get_version(&$request) { 96 97 $version = $request->get_parameter("oauth_version"); 98 if (!$version) { 99 // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present. 100 // Chapter 7.0 ("Accessing Protected Ressources") 101 $version = '1.0'; 102 } 103 if ($version !== $this->version) { 104 throw new OAuthException("OAuth version '$version' not supported"); 105 } 106 107 return $version; 108 109 } 110 111 /** 112 * figure out the signature with some defaults 113 */ 114 private function get_signature_method($request) { 115 116 $signature_method = $request instanceof OAuthRequest 117 ? $request->get_parameter('oauth_signature_method') : NULL; 118 119 if (!$signature_method) { 120 // According to chapter 7 ("Accessing Protected Ressources") the signature-method 121 // parameter is required, and we can't just fallback to PLAINTEXT 122 throw new OAuthException('No signature method parameter. This parameter is required'); 123 } 124 125 if (!in_array($signature_method, 126 array_keys($this->signature_methods))) { 127 throw new OAuthException( 128 "Signature method '$signature_method' not supported " . 129 'try one of the following: ' . 130 implode(', ', array_keys($this->signature_methods)) 131 ); 132 } 133 134 return $this->signature_methods[$signature_method]; 135 136 } 137 138 /** 139 * try to find the consumer for the provided request's consumer key 140 */ 141 private function get_consumer($request) { 142 143 $consumer_key = $request instanceof OAuthRequest 144 ? $request->get_parameter('oauth_consumer_key') : NULL; 145 146 if (!$consumer_key) { 147 throw new OAuthException('Invalid consumer key'); 148 } 149 150 $consumer = $this->data_store->lookup_consumer($consumer_key); 151 if (!$consumer) { 152 throw new OAuthException('Invalid consumer'); 153 } 154 155 return $consumer; 156 157 } 158 159 /** 160 * try to find the token for the provided request's token key 161 */ 162 private function get_token($request, $consumer, $token_type="access") { 163 164 $token_field = $request instanceof OAuthRequest 165 ? $request->get_parameter('oauth_token') : NULL; 166 167 $token = $this->data_store->lookup_token($consumer, $token_type, $token_field); 168 if (!$token) { 169 throw new OAuthException("Invalid $token_type token: $token_field"); 170 } 171 172 return $token; 173 174 } 175 176 /** 177 * all-in-one function to check the signature on a request 178 * should guess the signature method appropriately 179 */ 180 private function check_signature($request, $consumer, $token) { 181 182 // this should probably be in a different method 183 $timestamp = $request instanceof OAuthRequest 184 ? $request->get_parameter('oauth_timestamp') 185 : NULL; 186 $nonce = $request instanceof OAuthRequest 187 ? $request->get_parameter('oauth_nonce') 188 : NULL; 189 190 $this->check_timestamp($timestamp); 191 $this->check_nonce($consumer, $token, $nonce, $timestamp); 192 193 $signature_method = $this->get_signature_method($request); 194 195 $signature = $request->get_parameter('oauth_signature'); 196 $valid_sig = $signature_method->check_signature($request, $consumer, $token, $signature); 197 198 if (!$valid_sig) { 199 throw new OAuthException('Invalid signature'); 200 } 201 } 202 203 /** 204 * check that the timestamp is new enough 205 */ 206 private function check_timestamp($timestamp) { 207 if(!$timestamp) 208 throw new OAuthException('Missing timestamp parameter. The parameter is required'); 209 210 // verify that timestamp is recentish 211 $now = time(); 212 if (abs($now - $timestamp) > $this->timestamp_threshold) { 213 throw new OAuthException("Expired timestamp, yours $timestamp, ours $now"); 214 } 215 216 } 217 218 /** 219 * check that the nonce is not repeated 220 */ 221 private function check_nonce($consumer, $token, $nonce, $timestamp) { 222 223 if(!$nonce) 224 throw new OAuthException('Missing nonce parameter. The parameter is required'); 225 226 // verify that the nonce is uniqueish 227 $found = $this->data_store->lookup_nonce($consumer, $token, $nonce, $timestamp); 228 if ($found) { 229 throw new OAuthException("Nonce already used: $nonce"); 230 } 231 232 } 233 234 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body