OAuth2Client::getClientParams()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Maztech\Authentication;
4
5
use Maztech\InstagramApp;
6
use Maztech\InstagramRequest;
7
use Maztech\InstagramResponse;
8
use Maztech\InstagramClient;
9
use Maztech\Exceptions\InstagramResponseException;
10
use Maztech\Exceptions\InstagramSDKException;
11
12
/**
13
 * Class OAuth2Client
14
 *
15
 * @package Instagram
16
 */
17
class OAuth2Client
18
{
19
    /**
20
     * @const string The base authorization URL.
21
     */
22
    const BASE_AUTHORIZATION_URL = 'https://api.instagram.com';
23
24
    /**
25
     * The InstagramApp entity.
26
     *
27
     * @var InstagramApp
28
     */
29
    protected $app;
30
31
    /**
32
     * The Instagram client.
33
     *
34
     * @var InstagramClient
35
     */
36
    protected $client;
37
38
    /**
39
     * The version of the Graph API to use.
40
     *
41
     * @var string
42
     */
43
    protected $graphVersion;
44
45
    /**
46
     * The last request sent to Graph.
47
     *
48
     * @var InstagramRequest|null
49
     */
50
    protected $lastRequest;
51
52
    /**
53
     * @param InstagramApp    $app
54
     * @param InstagramClient $client
55
     * @param string|null    $graphVersion The version of the Graph API to use.
56
     */
57
    public function __construct(InstagramApp $app, InstagramClient $client)
58
    {
59
        $this->app = $app;
60
        $this->client = $client;
61
    }
62
63
    /**
64
     * Returns the last InstagramRequest that was sent.
65
     * Useful for debugging and testing.
66
     *
67
     * @return InstagramRequest|null
68
     */
69
    public function getLastRequest()
70
    {
71
        return $this->lastRequest;
72
    }
73
74
    /**
75
     * Generates an authorization URL to begin the process of authenticating a user.
76
     *
77
     * @param string $redirectUrl The callback URL to redirect to.
78
     * @param string $state       The CSPRNG-generated CSRF value.
79
     * @param array  $scope       An array of permissions to request.
80
     * @param array  $params      An array of parameters to generate URL.
81
     * @param string $separator   The separator to use in http_build_query().
82
     *
83
     * @return string
84
     */
85
    public function getAuthorizationUrl($redirectUrl, $state, array $scope = [], array $params = [], $separator = '&')
86
    {
87
        $params += [
88
            'client_id' => $this->app->getId(),
89
            'state' => $state,
90
            'response_type' => 'code',
91
            'redirect_uri' => $redirectUrl,
92
            'scope' => implode(',', $scope)
93
        ];
94
        
95
        return static::BASE_AUTHORIZATION_URL . '/oauth/authorize?' . http_build_query($params, '', $separator);
96
    }
97
98
    /**
99
     * Get a valid access token from a code.
100
     *
101
     * @param string $code
102
     * @param string $redirectUri
103
     *
104
     * @return AccessToken
105
     *
106
     * @throws InstagramSDKException
107
     */
108
    public function getAccessTokenFromCode($code, $redirectUri = '')
109
    {
110
        $params = [
111
            'code' => $code,
112
            'redirect_uri' => $redirectUri,
113
            'grant_type' => 'authorization_code'
114
        ];
115
116
        return $this->requestAnAccessToken($params);
117
    }
118
119
    /**
120
     * Exchanges a short-lived access token with a long-lived access token.
121
     *
122
     * @param AccessToken|string $accessToken
123
     *
124
     * @return AccessToken
125
     *
126
     * @throws InstagramSDKException
127
     */
128
    public function getLongLivedAccessToken($accessToken)
129
    {
130
        $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken;
131
        $params = [
132
            'grant_type' => 'fb_exchange_token',
133
            'fb_exchange_token' => $accessToken,
134
        ];
135
136
        return $this->requestAnAccessToken($params);
137
    }
138
139
    /**
140
     * Get a valid code from an access token.
141
     *
142
     * @param AccessToken|string $accessToken
143
     * @param string             $redirectUri
144
     *
145
     * @return AccessToken
146
     *
147
     * @throws InstagramSDKException
148
     */
149
    public function getCodeFromLongLivedAccessToken($accessToken, $redirectUri = '')
150
    {
151
        $params = [
152
            'redirect_uri' => $redirectUri,
153
        ];
154
155
        $response = $this->sendRequestWithClientParams('/oauth/client_code', $params, $accessToken);
156
        $data = $response->getDecodedBody();
157
158
        if (!isset($data['code'])) {
159
            throw new InstagramSDKException('Code was not returned from Graph.', 401);
160
        }
161
162
        return $data['code'];
163
    }
164
165
    /**
166
     * Send a request to the OAuth endpoint.
167
     *
168
     * @param array $params
169
     *
170
     * @return AccessToken
171
     *
172
     * @throws InstagramSDKException
173
     */
174
    protected function requestAnAccessToken(array $params)
175
    {
176
        $response = $this->sendRequestWithClientParams('/oauth/access_token', $params);
177
        $data = $response->getDecodedBody();
178
179
        if (!isset($data['access_token'])) {
180
            throw new InstagramSDKException('Access token was not returned from Graph.', 401);
181
        }
182
183
        // Graph returns two different key names for expiration time
184
        // on the same endpoint. Doh! :/
185
        $expiresAt = 0;
186
        if (isset($data['expires'])) {
187
            // For exchanging a short lived token with a long lived token.
188
            // The expiration time in seconds will be returned as "expires".
189
            $expiresAt = time() + $data['expires'];
190
        } elseif (isset($data['expires_in'])) {
191
            // For exchanging a code for a short lived access token.
192
            // The expiration time in seconds will be returned as "expires_in".
193
            // See: https://developers.facebook.com/docs/facebook-login/access-tokens#long-via-code
194
            $expiresAt = time() + $data['expires_in'];
195
        }
196
197
        return new AccessToken($data['access_token'], $expiresAt, $data['user_id']);
198
    }
199
200
    /**
201
     * Send a request to Graph with an app access token.
202
     *
203
     * @param string                  $endpoint
204
     * @param array                   $params
205
     * @param AccessToken|string|null $accessToken
206
     *
207
     * @return InstagramResponse
208
     *
209
     * @throws InstagramResponseException
210
     */
211
    protected function sendRequestWithClientParams($endpoint, array $params, $accessToken = null)
212
    {
213
        $params += $this->getClientParams();
214
215
        $accessToken = $accessToken ?: $this->app->getAccessToken();
216
217
        $this->lastRequest = new InstagramRequest(
218
            $this->app,
219
            $accessToken,
220
            'POST',
221
            $endpoint,
222
            $params,
223
            null
224
        );
225
226
        // dd($this->client, $params, $this->lastRequest );
227
        return $this->client->sendRequest($this->lastRequest, 'authorization');
228
    }
229
230
    /**
231
     * Returns the client_* params for OAuth requests.
232
     *
233
     * @return array
234
     */
235
    protected function getClientParams()
236
    {
237
        return [
238
            'client_id' => $this->app->getId(),
239
            'client_secret' => $this->app->getSecret(),
240
        ];
241
    }
242
}
243