Completed
Push — master ( 80eaf4...3b3c51 )
by Дмитрий
03:29
created

AbstractProvider::getScopeInline()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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