OAuthServer::get_token()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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