Completed
Push — master ( 2e0dc7...a0b296 )
by Дмитрий
05:36
created

AbstractProvider::getAuthorizeUri()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
ccs 0
cts 0
cp 0
c 0
b 0
f 0
nc 1
1
<?php
2
/**
3
 * SocialConnect project
4
 * @author: Patsura Dmitry https://github.com/ovr <[email protected]>
5
 */
6
7
namespace SocialConnect\OAuth2;
8
9
use InvalidArgumentException;
10
use SocialConnect\OAuth2\Exception\InvalidState;
11
use SocialConnect\OAuth2\Exception\UnknownAuthorization;
12
use SocialConnect\OAuth2\Exception\UnknownState;
13
use SocialConnect\Provider\AbstractBaseProvider;
14
use SocialConnect\Provider\Exception\InvalidAccessToken;
15
use SocialConnect\Provider\Exception\InvalidResponse;
16
use SocialConnect\Common\Http\Client\Client;
17
18
abstract class AbstractProvider extends AbstractBaseProvider
19
{
20
    /**
21
     * HTTP method for access token request
22
     *
23
     * @var string
24
     */
25
    protected $requestHttpMethod = Client::POST;
26
27
    /**
28
     * @return string
29
     */
30
    abstract public function getAuthorizeUri();
31
32
    /**
33
     * @return string
34
     */
35
    abstract public function getRequestTokenUri();
36
37
    /**
38
     * Default parameters for auth url, can be redeclared inside implementation of the Provider
39
     *
40
     * @return array
41
     */
42 16
    public function getAuthUrlParameters()
43
    {
44
        return [
45 16
            'client_id' => $this->consumer->getKey(),
46 16
            'redirect_uri' => $this->getRedirectUrl(),
47 16
            'response_type' => 'code',
48 16
        ];
49
    }
50
51
    /**
52
     * @return string
53
     */
54 16
    protected function generateState()
55
    {
56 16
        return md5(
57 16
            time() . mt_rand()
58 16
        );
59
    }
60
61
    /**
62
     * @return string
63
     */
64 16
    public function makeAuthUrl()
65
    {
66 16
        $urlParameters = $this->getAuthUrlParameters();
67
68 16
        $this->session->set(
69 16
            'oauth2_state',
70 16
            $urlParameters['state'] = $this->generateState()
71 16
        );
72
73 16
        if (count($this->scope) > 0) {
74
            $urlParameters['scope'] = $this->getScopeInline();
75
        }
76
77 16
        if (count($this->fields) > 0) {
78
            $urlParameters['fields'] = $this->getFieldsInline();
79
        }
80
81 16
        return $this->getAuthorizeUri() . '?' . http_build_query($urlParameters);
82
    }
83
84
    /**
85
     * Parse access token from response's $body
86
     *
87
     * @param string|bool $body
88
     * @return AccessToken
89
     * @throws InvalidAccessToken
90
     */
91 5
    public function parseToken($body)
92
    {
93 5
        if (empty($body)) {
94
            throw new InvalidAccessToken('Provider response with empty body');
95
        }
96
97 5
        parse_str($body, $token);
98
99 5
        if (!is_array($token) || !isset($token['access_token'])) {
100 4
            throw new InvalidAccessToken('Provider API returned an unexpected response');
101
        }
102
103 1
        return new AccessToken($token);
104
    }
105
106
    /**
107
     * @param string $code
108
     * @return \SocialConnect\Common\Http\Request
109
     */
110 17
    protected function makeAccessTokenRequest($code)
111
    {
112
        $parameters = [
113 17
            'client_id' => $this->consumer->getKey(),
114 17
            'client_secret' => $this->consumer->getSecret(),
115 17
            'code' => $code,
116 17
            'grant_type' => 'authorization_code',
117 17
            'redirect_uri' => $this->getRedirectUrl()
118 17
        ];
119
120 17
        return new \SocialConnect\Common\Http\Request(
121 17
            $this->getRequestTokenUri(),
122 17
            $parameters,
123 17
            $this->requestHttpMethod,
124
            [
125
                'Content-Type' => 'application/x-www-form-urlencoded'
126 17
            ]
127 17
        );
128
    }
129
130
    /**
131
     * @param string $code
132
     * @return AccessToken
133
     * @throws InvalidResponse
134
     */
135 32
    public function getAccessToken($code)
136
    {
137 32
        if (!is_string($code)) {
138 16
            throw new InvalidArgumentException('Parameter $code must be a string');
139
        }
140
141 16
        $response = $this->httpClient->fromRequest(
142 16
            $this->makeAccessTokenRequest($code)
143 16
        );
144
145 16
        if (!$response->isSuccess()) {
146 16
            throw new InvalidResponse(
147 16
                'API response with error code',
148
                $response
149 16
            );
150
        }
151
152
        $body = $response->getBody();
153
        return $this->parseToken($body);
154
    }
155
156
    /**
157
     * @param array $parameters
158
     * @return AccessToken
159
     * @throws \SocialConnect\OAuth2\Exception\InvalidState
160
     * @throws \SocialConnect\OAuth2\Exception\UnknownState
161
     * @throws \SocialConnect\OAuth2\Exception\UnknownAuthorization
162
     */
163
    public function getAccessTokenByRequestParameters(array $parameters)
164
    {
165
        $state = $this->session->get('oauth2_state');
166
        if (!$state) {
167
            throw new UnknownAuthorization();
168
        }
169
170
        if (!isset($parameters['state'])) {
171
            throw new UnknownState();
172
        }
173
174
        if ($state !== $parameters['state']) {
175
            throw new InvalidState();
176
        }
177
178
        return $this->getAccessToken($parameters['code']);
179
    }
180
}
181