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