Completed
Pull Request — 5.x (#926)
by
unknown
116:02 queued 114:13
created

AccessTokenMetadata::getProperty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright 2017 Facebook, Inc.
4
 *
5
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
 * use, copy, modify, and distribute this software in source code or binary
7
 * form for use in connection with the web services and APIs provided by
8
 * Facebook.
9
 *
10
 * As with any software that integrates with the Facebook platform, your use
11
 * of this software is subject to the Facebook Developer Principles and
12
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
 * shall be included in all copies or substantial portions of the software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
namespace Facebook\Authentication;
25
26
use Facebook\Exceptions\FacebookSDKException;
27
28
/**
29
 * Class AccessTokenMetadata
30
 *
31
 * Represents metadata from an access token.
32
 *
33
 * @package Facebook
34
 * @see     https://developers.facebook.com/docs/graph-api/reference/debug_token
35
 */
36
class AccessTokenMetadata
37
{
38
    /**
39
     * The access token metadata.
40
     *
41
     * @var array
42
     */
43
    protected $metadata = [];
44
45
    /**
46
     * Properties that should be cast as DateTime objects.
47
     *
48
     * @var array
49
     */
50
    protected static $dateProperties = ['expires_at', 'issued_at'];
51
52
    /**
53
     * @param array $metadata
54
     *
55
     * @throws FacebookSDKException
56
     */
57
    public function __construct(array $metadata)
58
    {
59
        if (!isset($metadata['data'])) {
60
            throw new FacebookSDKException('Unexpected debug token response data.', 401);
61
        }
62
63
        $this->metadata = $metadata['data'];
64
65
        $this->castTimestampsToDateTime();
66
    }
67
68
    /**
69
     * Returns a value from the metadata.
70
     *
71
     * @param string $field   The property to retrieve.
72
     * @param mixed  $default The default to return if the property doesn't exist.
73
     *
74
     * @return mixed
75
     */
76
    public function getField($field, $default = null)
77
    {
78
        if (isset($this->metadata[$field])) {
79
            return $this->metadata[$field];
80
        }
81
82
        return $default;
83
    }
84
85
    /**
86
     * Returns a value from a child property in the metadata.
87
     *
88
     * @param string $parentField The parent property.
89
     * @param string $field       The property to retrieve.
90
     * @param mixed  $default     The default to return if the property doesn't exist.
91
     *
92
     * @return mixed
93
     */
94
    public function getChildProperty($parentField, $field, $default = null)
95
    {
96
        if (!isset($this->metadata[$parentField])) {
97
            return $default;
98
        }
99
100
        if (!isset($this->metadata[$parentField][$field])) {
101
            return $default;
102
        }
103
104
        return $this->metadata[$parentField][$field];
105
    }
106
107
    /**
108
     * Returns a value from the error metadata.
109
     *
110
     * @param string $field   The property to retrieve.
111
     * @param mixed  $default The default to return if the property doesn't exist.
112
     *
113
     * @return mixed
114
     */
115
    public function getErrorProperty($field, $default = null)
116
    {
117
        return $this->getChildProperty('error', $field, $default);
118
    }
119
120
    /**
121
     * Returns a value from the "metadata" metadata. *Brain explodes*
122
     *
123
     * @param string $field   The property to retrieve.
124
     * @param mixed  $default The default to return if the property doesn't exist.
125
     *
126
     * @return mixed
127
     */
128
    public function getMetadataProperty($field, $default = null)
129
    {
130
        return $this->getChildProperty('metadata', $field, $default);
131
    }
132
133
    /**
134
     * The ID of the application this access token is for.
135
     *
136
     * @return string|null
137
     */
138
    public function getAppId()
139
    {
140
        return $this->getField('app_id');
141
    }
142
143
    /**
144
     * Name of the application this access token is for.
145
     *
146
     * @return string|null
147
     */
148
    public function getApplication()
149
    {
150
        return $this->getField('application');
151
    }
152
153
    /**
154
     * Any error that a request to the graph api
155
     * would return due to the access token.
156
     *
157
     * @return bool|null
158
     */
159
    public function isError()
160
    {
161
        return $this->getField('error') !== null;
162
    }
163
164
    /**
165
     * The error code for the error.
166
     *
167
     * @return int|null
168
     */
169
    public function getErrorCode()
170
    {
171
        return $this->getErrorProperty('code');
172
    }
173
174
    /**
175
     * The error message for the error.
176
     *
177
     * @return string|null
178
     */
179
    public function getErrorMessage()
180
    {
181
        return $this->getErrorProperty('message');
182
    }
183
184
    /**
185
     * The error subcode for the error.
186
     *
187
     * @return int|null
188
     */
189
    public function getErrorSubcode()
190
    {
191
        return $this->getErrorProperty('subcode');
192
    }
193
194
    /**
195
     * DateTime when this access token expires.
196
     *
197
     * @return \DateTime|null
198
     */
199
    public function getExpiresAt()
200
    {
201
        return $this->getField('expires_at');
202
    }
203
204
    /**
205
     * Whether the access token is still valid or not.
206
     *
207
     * @return boolean|null
208
     */
209
    public function getIsValid()
210
    {
211
        return $this->getField('is_valid');
212
    }
213
214
    /**
215
     * DateTime when this access token was issued.
216
     *
217
     * Note that the issued_at field is not returned
218
     * for short-lived access tokens.
219
     *
220
     * @see https://developers.facebook.com/docs/facebook-login/access-tokens#debug
221
     *
222
     * @return \DateTime|null
223
     */
224
    public function getIssuedAt()
225
    {
226
        return $this->getField('issued_at');
227
    }
228
229
    /**
230
     * General metadata associated with the access token.
231
     * Can contain data like 'sso', 'auth_type', 'auth_nonce'.
232
     *
233
     * @return array|null
234
     */
235
    public function getMetadata()
236
    {
237
        return $this->getField('metadata');
238
    }
239
240
    /**
241
     * The 'sso' child property from the 'metadata' parent property.
242
     *
243
     * @return string|null
244
     */
245
    public function getSso()
246
    {
247
        return $this->getMetadataProperty('sso');
248
    }
249
250
    /**
251
     * The 'auth_type' child property from the 'metadata' parent property.
252
     *
253
     * @return string|null
254
     */
255
    public function getAuthType()
256
    {
257
        return $this->getMetadataProperty('auth_type');
258
    }
259
260
    /**
261
     * The 'auth_nonce' child property from the 'metadata' parent property.
262
     *
263
     * @return string|null
264
     */
265
    public function getAuthNonce()
266
    {
267
        return $this->getMetadataProperty('auth_nonce');
268
    }
269
270
    /**
271
     * For impersonated access tokens, the ID of
272
     * the page this token contains.
273
     *
274
     * @return string|null
275
     */
276
    public function getProfileId()
277
    {
278
        return $this->getField('profile_id');
279
    }
280
281
    /**
282
     * List of permissions that the user has granted for
283
     * the app in this access token.
284
     *
285
     * @return array
286
     */
287
    public function getScopes()
288
    {
289
        return $this->getField('scopes');
290
    }
291
292
    /**
293
     * The ID of the user this access token is for.
294
     *
295
     * @return string|null
296
     */
297
    public function getUserId()
298
    {
299
        return $this->getField('user_id');
300
    }
301
302
    /**
303
     * Ensures the app ID from the access token
304
     * metadata is what we expect.
305
     *
306
     * @param string $appId
307
     *
308
     * @throws FacebookSDKException
309
     */
310
    public function validateAppId($appId)
311
    {
312
        if ($this->getAppId() !== $appId) {
313
            throw new FacebookSDKException('Access token metadata contains unexpected app ID.', 401);
314
        }
315
    }
316
317
    /**
318
     * Ensures the user ID from the access token
319
     * metadata is what we expect.
320
     *
321
     * @param string $userId
322
     *
323
     * @throws FacebookSDKException
324
     */
325
    public function validateUserId($userId)
326
    {
327
        if ($this->getUserId() !== $userId) {
328
            throw new FacebookSDKException('Access token metadata contains unexpected user ID.', 401);
329
        }
330
    }
331
332
    /**
333
     * Ensures the access token has not expired yet.
334
     *
335
     * @throws FacebookSDKException
336
     */
337
    public function validateExpiration()
338
    {
339
        if (!$this->getExpiresAt() instanceof \DateTime) {
340
            return;
341
        }
342
343
        if ($this->getExpiresAt()->getTimestamp() < time()) {
344
            throw new FacebookSDKException('Inspection of access token metadata shows that the access token has expired.', 401);
345
        }
346
    }
347
348
    /**
349
     * Converts a unix timestamp into a DateTime entity.
350
     *
351
     * @param int $timestamp
352
     *
353
     * @return \DateTime
354
     */
355
    private function convertTimestampToDateTime($timestamp)
356
    {
357
        $dt = new \DateTime();
358
        $dt->setTimestamp($timestamp);
359
360
        return $dt;
361
    }
362
363
    /**
364
     * Casts the unix timestamps as DateTime entities.
365
     */
366
    private function castTimestampsToDateTime()
367
    {
368
        foreach (static::$dateProperties as $key) {
369
            if (isset($this->metadata[$key]) && $this->metadata[$key] !== 0) {
370
                $this->metadata[$key] = $this->convertTimestampToDateTime($this->metadata[$key]);
371
            }
372
        }
373
    }
374
}
375