AbstractProvider::parseToken()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 0
cts 7
cp 0
rs 9.5222
c 0
b 0
f 0
cc 5
nc 3
nop 1
crap 30
1
<?php
2
/**
3
 * SocialConnect project
4
 * @author: Patsura Dmitry https://github.com/ovr <[email protected]>
5
 */
6
declare(strict_types=1);
7
8
namespace SocialConnect\OAuth1;
9
10
use SocialConnect\Common\Http\Client\ClientInterface;
11
use SocialConnect\OAuth1\Exception\UnknownAuthorization;
12
use SocialConnect\Provider\AbstractBaseProvider;
13
use SocialConnect\Provider\Consumer;
14
use SocialConnect\Provider\Exception\InvalidAccessToken;
15
use SocialConnect\Provider\Exception\InvalidResponse;
16
use SocialConnect\Common\Http\Client\Client;
17
use SocialConnect\OAuth1\Exception\InvalidRequestToken;
18
use SocialConnect\OAuth1\Signature\MethodHMACSHA1;
19
use SocialConnect\Provider\Session\SessionInterface;
20
21
abstract class AbstractProvider extends AbstractBaseProvider
22
{
23
    /**
24
     * @var string
25
     */
26
    protected $oauth1Version = '1.0a';
27
28
    /**
29
     * @var string
30
     */
31
    protected $requestTokenMethod = Client::POST;
32
33
    /**
34
     * @var Consumer
35
     */
36
    protected $consumer;
37
38
    /**
39
     * @var Token
40
     */
41
    protected $consumerToken;
42
43
    /**
44
     * @var array
45
     */
46
    protected $scope = [];
47
48
    /**
49
     * @var  \SocialConnect\OAuth1\Signature\AbstractSignatureMethod
50
     */
51
    protected $signature;
52
53
    /**
54
     * @param ClientInterface $httpClient
55
     * @param Consumer $consumer
56
     * @param array $parameters
57
     */
58 2
    public function __construct(ClientInterface $httpClient, SessionInterface $session, Consumer $consumer, array $parameters)
59
    {
60 2
        parent::__construct($httpClient, $session, $consumer, $parameters);
61
62 2
        $this->consumerToken = new Token('', '');
63
64 2
        $this->signature = new MethodHMACSHA1();
65 2
    }
66
67
    /**
68
     * @return string
69
     */
70
    abstract public function getAuthorizeUri();
71
72
    /**
73
     * @return string
74
     */
75
    abstract public function getRequestTokenUri();
76
77
    /**
78
     * @return string
79
     */
80
    abstract public function getRequestTokenAccessUri();
81
82
    /**
83
     * @return Token
84
     * @throws InvalidResponse
85
     */
86
    protected function requestAuthToken()
87
    {
88
        $parameters = [];
89
90
        /**
91
         * OAuth Core 1.0 Revision A: oauth_callback: An absolute URL to which the Service Provider will redirect
92
         * the User back when the Obtaining User Authorization step is completed.
93
         *
94
         * http://oauth.net/core/1.0a/#auth_step1
95
         */
96
        if ('1.0a' == $this->oauth1Version) {
97
            $parameters['oauth_callback'] = $this->getRedirectUrl();
98
        }
99
100
        $response = $this->oauthRequest(
101
            $this->getRequestTokenUri(),
102
            $this->requestTokenMethod,
103
            $parameters
104
        );
105
106
        if ($response->isSuccess()) {
107
            $token = $this->parseToken($response->getBody());
108
109
110
            $this->session->set('oauth1_request_token', $token);
111
112
            return $token;
113
        }
114
115
        throw new InvalidResponse('Provider response is not success');
116
    }
117
118
    /**
119
     * Parse Token from response's $body
120
     *
121
     * @param string|boolean $body
122
     * @return Token
123
     * @throws InvalidRequestToken
124
     * @throws InvalidResponse
125
     */
126
    public function parseToken($body)
127
    {
128
        if (empty($body)) {
129
            throw new InvalidResponse('Provider response with empty body');
130
        }
131
132
        parse_str($body, $token);
133
        if (!is_array($token) || !isset($token['oauth_token']) || !isset($token['oauth_token_secret'])) {
134
            throw new InvalidRequestToken;
135
        }
136
137
        return new Token($token['oauth_token'], $token['oauth_token_secret']);
138
    }
139
140
    /**
141
     * @param string $uri
142
     * @param string $method
143
     * @param array $parameters
144
     * @return \SocialConnect\Common\Http\Response
145
     */
146
    public function oauthRequest($uri, $method = Client::GET, $parameters = [], $headers = [])
147
    {
148
        $headers = array_merge([
149
            'Accept' => 'application/json'
150
        ], $headers);
151
152
        if ($method == Client::POST) {
153
            $headers['Content-Type'] = 'application/x-www-form-urlencoded';
154
        }
155
156
        $parameters = array_merge(
157
            [
158
                'oauth_version' => '1.0',
159
                'oauth_nonce' => md5(time() . mt_rand()),
160
                'oauth_timestamp' => time(),
161
                'oauth_consumer_key' => $this->consumer->getKey()
162
            ],
163
            $parameters
164
        );
165
166
        $request = new Request(
167
            $uri,
168
            $parameters,
169
            $method,
170
            $headers
171
        );
172
173
        $request->signRequest(
174
            $this->signature,
175
            $this->consumer,
176
            $this->consumerToken
177
        );
178
179
        return $this->httpClient->fromRequest($request);
180
    }
181
182
    /**
183
     * {@inheritdoc}
184
     */
185
    public function makeAuthUrl(): string
186
    {
187
        $urlParameters = [
188
            'oauth_token' => $this->requestAuthToken()->getKey()
189
        ];
190
191
        return $this->getAuthorizeUri() . '?' . http_build_query($urlParameters, '', '&');
192
    }
193
194
    /**
195
     * @param array $parameters
196
     * @return AccessToken
197
     * @throws \SocialConnect\OAuth1\Exception\UnknownAuthorization
198
     */
199
    public function getAccessTokenByRequestParameters(array $parameters)
200
    {
201
        $token = $this->session->get('oauth1_request_token');
202
        if (!$token) {
203
            throw new UnknownAuthorization();
204
        }
205
206
        $this->session->delete('oauth1_request_token');
207
208
        return $this->getAccessToken($token, $parameters['oauth_verifier']);
209
    }
210
211
    /**
212
     * @param Token $token
213
     * @param $oauthVerifier
214
     * @return AccessToken
215
     * @throws InvalidResponse
216
     */
217
    public function getAccessToken(Token $token, $oauthVerifier)
218
    {
219
        $this->consumerToken = $token;
220
221
        $parameters = [
222
            'oauth_consumer_key' => $this->consumer->getKey(),
223
            'oauth_token' => $token->getKey(),
224
            'oauth_verifier' => $oauthVerifier
225
        ];
226
227
        $response = $this->oauthRequest(
228
            $this->getRequestTokenAccessUri(),
229
            $this->requestTokenMethod,
230
            $parameters
231
        );
232
233
        if ($response->getStatusCode() === 200) {
234
            return $this->parseAccessToken($response->getBody());
235
        }
236
237
        throw new InvalidResponse(
238
            'Unexpected response code',
239
            $response
240
        );
241
    }
242
243
    /**
244
     * Parse AccessToken from response's $body
245
     *
246
     * @param string|boolean $body
247
     * @return AccessToken
248
     * @throws InvalidAccessToken
249
     * @throws InvalidResponse
250
     */
251
    public function parseAccessToken($body)
252
    {
253
        if (empty($body)) {
254
            throw new InvalidResponse('Provider response with empty body');
255
        }
256
257
        parse_str($body, $token);
258
        if (!is_array($token) || !isset($token['oauth_token']) || !isset($token['oauth_token_secret'])) {
259
            throw new InvalidAccessToken;
260
        }
261
262
        $accessToken = new AccessToken($token['oauth_token'], $token['oauth_token_secret']);
263
        if (isset($token['user_id'])) {
264
            $accessToken->setUserId($token['user_id']);
265
        }
266
267
        return $accessToken;
268
    }
269
270
    /**
271
     * @return array
272
     */
273
    public function getScope()
274
    {
275
        return $this->scope;
276
    }
277
278
    /**
279
     * @param array $scope
280
     */
281
    public function setScope(array $scope)
282
    {
283
        $this->scope = $scope;
284
    }
285
286
    /**
287
     * @param Token $token
288
     */
289
    public function setConsumerToken(Token $token)
290
    {
291
        $this->consumerToken = $token;
292
    }
293
294
    /**
295
     * @return \SocialConnect\OAuth1\Token
296
     */
297
    public function getConsumerToken()
298
    {
299
        return $this->consumerToken;
300
    }
301
}
302