krz/vox-populi

A Tumblr web client.

clone: git clone https://gitbay.org/krz/vox-populi.git

main: vendor/eher/oauth/src/Eher/OAuth/OAuthServer.php · raw

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