LTI Integration Library 4.10.3
PHP class library for building LTI integrations
 
Loading...
Searching...
No Matches
OAuthServer.php
1<?php
2
3namespace ceLTIc\LTI\OAuth;
4
13{
14
20 protected $timestamp_threshold = 300; // in seconds, five minutes
21
27 protected $version = '1.0';
28
34 protected $signature_methods = array();
35
41 protected $data_store;
42
49 {
50 $this->data_store = $data_store;
51 }
52
58 public function add_signature_method($signature_method)
59 {
60 $this->signature_methods[$signature_method->get_name()] = $signature_method;
61 }
62
63 // high level functions
64
74 public function fetch_request_token(&$request)
75 {
76 $this->get_version($request);
77
78 $consumer = $this->get_consumer($request);
79
80 // no token required for the initial token request
81 $token = null;
82
83 $this->check_signature($request, $consumer, $token);
84
85 // Rev A change
86 $callback = $request->get_parameter('oauth_callback');
87 $new_token = $this->data_store->new_request_token($consumer, $callback);
88
89 return $new_token;
90 }
91
101 public function fetch_access_token(&$request)
102 {
103 $this->get_version($request);
104
105 $consumer = $this->get_consumer($request);
106
107 // requires authorized request token
108 $token = $this->get_token($request, $consumer, "request");
109
110 $this->check_signature($request, $consumer, $token);
111
112 // Rev A change
113 $verifier = $request->get_parameter('oauth_verifier');
114 $new_token = $this->data_store->new_access_token($token, $consumer, $verifier);
115
116 return $new_token;
117 }
118
126 public function verify_request(&$request)
127 {
128 $this->get_version($request);
129 $consumer = $this->get_consumer($request);
130 $token = $this->get_token($request, $consumer, "access");
131 $this->check_signature($request, $consumer, $token);
132
133 return array($consumer, $token);
134 }
135
136 // Internals from here
137
148 private function get_version(&$request)
149 {
150 $version = $request->get_parameter("oauth_version");
151 if (!$version) {
152 // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present.
153 // Chapter 7.0 ("Accessing Protected Ressources")
154 $version = '1.0';
155 }
156 if ($version !== $this->version) {
157 throw new OAuthException("OAuth version '$version' not supported");
158 }
159
160 return $version;
161 }
162
171 private function get_signature_method($request)
172 {
173 $signature_method = $request instanceof OAuthRequest ? $request->get_parameter('oauth_signature_method') : null;
174
175 if (!$signature_method) {
176 // According to chapter 7 ("Accessing Protected Ressources") the signature-method
177 // parameter is required, and we can't just fallback to PLAINTEXT
178 throw new OAuthException('No signature method parameter. This parameter is required');
179 }
180
181 if (!in_array($signature_method, array_keys($this->signature_methods))) {
182 throw new OAuthException(
183 "Signature method '$signature_method' not supported " .
184 'try one of the following: ' .
185 implode(', ', array_keys($this->signature_methods))
186 );
187 }
188
189 return $this->signature_methods[$signature_method];
190 }
191
200 private function get_consumer($request)
201 {
202 $consumer_key = $request instanceof OAuthRequest ? $request->get_parameter('oauth_consumer_key') : null;
203
204 if (is_null($consumer_key) || (strlen($consumer_key) <= 0)) {
205 throw new OAuthException('Invalid consumer key');
206 }
207
208 $consumer = $this->data_store->lookup_consumer($consumer_key);
209 if (!$consumer) {
210 throw new OAuthException('Invalid consumer');
211 }
212
213 return $consumer;
214 }
215
226 private function get_token($request, $consumer, $token_type = "access")
227 {
228 $token_field = $request instanceof OAuthRequest ? $request->get_parameter('oauth_token') : null;
229
230 $token = $this->data_store->lookup_token($consumer, $token_type, $token_field);
231 if (!$token) {
232 throw new OAuthException("Invalid $token_type token: $token_field");
233 }
234
235 return $token;
236 }
237
246 private function check_signature($request, $consumer, $token)
247 {
248 // this should probably be in a different method
249 $timestamp = $request instanceof OAuthRequest ? $request->get_parameter('oauth_timestamp') : null;
250 $nonce = $request instanceof OAuthRequest ? $request->get_parameter('oauth_nonce') : null;
251
252 $this->check_timestamp($timestamp);
253 $this->check_nonce($consumer, $token, $nonce, $timestamp);
254
255 $signature_method = $this->get_signature_method($request);
256
257 $signature = $request->get_parameter('oauth_signature');
258 $valid_sig = $signature_method->check_signature($request, $consumer, $token, $signature);
259
260 if (!$valid_sig) {
261 throw new OAuthException('Invalid signature');
262 }
263 }
264
271 private function check_timestamp($timestamp)
272 {
273 if (!$timestamp)
274 throw new OAuthException('Missing timestamp parameter. The parameter is required');
275
276 // verify that timestamp is recentish
277 $now = time();
278 if (abs($now - $timestamp) > $this->timestamp_threshold) {
279 throw new OAuthException("Expired timestamp, yours $timestamp, ours $now");
280 }
281 }
282
292 private function check_nonce($consumer, $token, $nonce, $timestamp)
293 {
294 if (!$nonce)
295 throw new OAuthException('Missing nonce parameter. The parameter is required');
296
297 // verify that the nonce is uniqueish
298 $found = $this->data_store->lookup_nonce($consumer, $token, $nonce, $timestamp);
299 if ($found) {
300 throw new OAuthException("Nonce already used: $nonce");
301 }
302 }
303
304}
Class to represent an OAuth Exception.
Class to represent an OAuth server.
fetch_access_token(&$request)
Process an access_token request.
$timestamp_threshold
Timestamp threshhold.
verify_request(&$request)
Verify an API call, checks all the parameters.
add_signature_method($signature_method)
Add a signature method.
__construct($data_store)
Class constructor.
$signature_methods
Signature methods.
fetch_request_token(&$request)
Process a request_token request.