Completed
Pull Request — master (#35)
by Andreas
04:39
created

AbstractProvider::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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