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}