Completed
Branch master (bda8d5)
by Дмитрий
02:19
created

SmashCast::getAccessTokenByRequestParameters()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 11
dl 0
loc 22
rs 9.2222
c 2
b 0
f 1
ccs 0
cts 12
cp 0
cc 6
nc 9
nop 1
crap 42
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\OAuth2\Provider;
9
10
use SocialConnect\Common\Http\Client\Client;
11
use SocialConnect\OAuth2\Exception\InvalidState;
12
use SocialConnect\OAuth2\Exception\UnknownAuthorization;
13
use SocialConnect\OAuth2\Exception\UnknownState;
14
use SocialConnect\Provider\AccessTokenInterface;
15
use SocialConnect\Provider\Exception\InvalidAccessToken;
16
use SocialConnect\Provider\Exception\InvalidResponse;
17
use SocialConnect\OAuth2\AccessToken;
18
use SocialConnect\Common\Entity\User;
19
use SocialConnect\Common\Hydrator\ObjectMap;
20
21
class SmashCast extends \SocialConnect\OAuth2\AbstractProvider
22
{
23
    const NAME = 'smashcast';
24
25
    /**
26
     * {@inheritdoc}
27
     */
28
    public function getBaseUri()
29
    {
30
        return 'https://api.smashcast.tv/';
31
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function getAuthorizeUri()
37
    {
38
        return 'https://api.smashcast.tv/oauth/login';
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44
    public function getRequestTokenUri()
45
    {
46
        return 'https://api.smashcast.tv/oauth/exchange';
47
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52
    public function getName()
53
    {
54
        return self::NAME;
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60
    public function getAuthUrlParameters(): array
61
    {
62
        $parameters = $this->getArrayOption('auth.parameters', []);
63
64
        // Because SmashCast developers dont know about OAuth spec...
65
        $parameters['app_token'] = $this->consumer->getKey();
66
        $parameters['redirect_uri'] = $this->getRedirectUrl();
67
        $parameters['response_type'] = 'code';
68
69
        return $parameters;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function parseToken($body)
76
    {
77
        if (empty($body)) {
78
            throw new InvalidAccessToken('Provider response with empty body');
79
        }
80
81
        $result = json_decode($body, true);
82
        if ($result) {
83
            return new AccessToken($result);
84
        }
85
86
        throw new InvalidAccessToken('Provider response with not valid JSON');
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    protected function makeAccessTokenRequest($code)
93
    {
94
        $parameters = [
95
            'request_token' => $code,
96
            'app_token' => $this->consumer->getKey(),
97
            'hash' => base64_encode($this->consumer->getKey() . $this->consumer->getSecret()),
98
        ];
99
100
        return new \SocialConnect\Common\Http\Request(
101
            $this->getRequestTokenUri(),
102
            $parameters,
103
            $this->requestHttpMethod,
104
            [
105
                'Content-Type' => 'application/x-www-form-urlencoded'
106
            ]
107
        );
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function getAccessTokenByRequestParameters(array $parameters)
114
    {
115
        if (!$this->getBoolOption('stateless', false)) {
116
            $state = $this->session->get('oauth2_state');
117
            if (!$state) {
118
                throw new UnknownAuthorization();
119
            }
120
        }
121
122
        if (!isset($parameters['state'])) {
123
            throw new UnknownState();
124
        }
125
126
        if ($state !== $parameters['state']) {
127
            throw new InvalidState();
128
        }
129
130
        if (isset($parameters['authToken'])) {
131
            return new AccessToken(['access_token' => $parameters['authToken']]);
132
        }
133
134
        return $this->getAccessToken($parameters['request_token']);
135
    }
136
137
    /**
138
     * This method it needed, because I cannot fix auth/login with accessToken
139
     * BTW: Yes, I known that it's unneeded round trip to the server
140
     *
141
     * @param AccessTokenInterface $accessToken
142
     * @return mixed
143
     * @throws InvalidResponse
144
     */
145
    protected function getUserNameByToken(AccessTokenInterface $accessToken)
146
    {
147
        $response = $this->httpClient->request(
148
            $this->getBaseUri() . 'userfromtoken/' . $accessToken->getToken()
149
        );
150
151
        if (!$response->isSuccess()) {
152
            throw new InvalidResponse(
153
                'API response with error code',
154
                $response
155
            );
156
        }
157
158
        $result = $response->json();
159
160
        if (!$result) {
161
            throw new InvalidResponse(
162
                'API response is not a valid JSON object',
163
                $response
164
            );
165
        }
166
167
        return $result->user_name;
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function getIdentity(AccessTokenInterface $accessToken)
174
    {
175
        // @todo Find a problem with this code
176
        /*$response = $this->httpClient->request(
177
            $this->getBaseUri() . 'auth/login',
178
            [
179
                'app' => 'desktop', // @any app name, not working, I was using JSON and not working..
180
                'authToken' => $accessToken->getToken()
181
            ],
182
            Client::POST,
183
            [
184
                'Content-Type' => 'application/x-www-form-urlencoded'
185
            ]
186
        );*/
187
188
        $username = $this->getUserNameByToken($accessToken);
189
190
        $response = $this->httpClient->request(
191
            $this->getBaseUri() . 'user/' . $username,
192
            [
193
                'authToken' => $accessToken->getToken()
194
            ]
195
        );
196
197
        if (!$response->isSuccess()) {
198
            throw new InvalidResponse(
199
                'API response with error code',
200
                $response
201
            );
202
        }
203
204
        $result = $response->json();
205
206
        if (!$result) {
207
            throw new InvalidResponse(
208
                'API response is not a valid JSON object',
209
                $response
210
            );
211
        }
212
213
        $hydrator = new ObjectMap(
214
            [
215
                'user_id' => 'id',
216
                'user_name' => 'username',
217
                'user_email' => 'email',
218
            ]
219
        );
220
221
        return $hydrator->hydrate(new User(), $result);
222
    }
223
}
224