Failed Conditions
Pull Request — ng (#68)
by Florent
23:16 queued 19:02
created

Authorization::addScope()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2018 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Component\Server\AuthorizationEndpoint;
15
16
use OAuth2Framework\Component\Server\AuthorizationEndpoint\ResponseMode\ResponseMode;
17
use OAuth2Framework\Component\Server\Core\Client\Client;
18
use OAuth2Framework\Component\Server\Core\ResourceServer\ResourceServer;
19
use OAuth2Framework\Component\Server\Core\UserAccount\UserAccount;
20
use OAuth2Framework\Component\Server\TokenType\TokenType;
21
22
final class Authorization
23
{
24
    /**
25
     * @var bool|null
26
     */
27
    private $authorized = null;
28
29
    /**
30
     * @var Client
31
     */
32
    private $client;
33
34
    /**
35
     * @var UserAccount|null
36
     */
37
    private $userAccount = null;
38
39
    /**
40
     * @var null|bool
41
     */
42
    private $userAccountFullyAuthenticated = null;
43
44
    /**
45
     * @var string[]
46
     */
47
    private $scopes = [];
48
49
    /**
50
     * @var array
51
     */
52
    private $data = [];
53
54
    /**
55
     * @var TokenType|null
56
     */
57
    private $tokenType = null;
58
59
    /**
60
     * @var ResponseType[]
61
     */
62
    private $responseTypes = [];
63
64
    /**
65
     * @var ResponseMode|null
66
     */
67
    private $responseMode = null;
68
69
    /**
70
     * @var array
71
     */
72
    private $queryParameters = [];
73
74
    /**
75
     * @var string|null
76
     */
77
    private $redirectUri = null;
78
79
    /**
80
     * @var array
81
     */
82
    private $consentScreenOptions = [];
83
84
    /**
85
     * @var array
86
     */
87
    private $responseParameters = [];
88
89
    /**
90
     * @var array
91
     */
92
    private $responseHeaders = [];
93
94
    /**
95
     * @var null|ResourceServer
96
     */
97
    private $resourceServer = null;
98
99
    /**
100
     * Authorization constructor.
101
     *
102
     * @param Client $client
103
     * @param array  $queryParameters
104
     */
105
    private function __construct(Client $client, array $queryParameters)
106
    {
107
        $this->client = $client;
108
        $this->queryParameters = $queryParameters;
109
    }
110
111
    /**
112
     * @param Client $client
113
     * @param array  $queryParameters
114
     *
115
     * @return Authorization
0 ignored issues
show
Documentation introduced by
Should the return type not be \self?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
116
     */
117
    public static function create(Client $client, array $queryParameters): self
118
    {
119
        return new self($client, $queryParameters);
120
    }
121
122
    /**
123
     * @return array
124
     */
125
    public function getQueryParams(): array
126
    {
127
        return $this->queryParameters;
128
    }
129
130
    /**
131
     * @param string $param
132
     *
133
     * @return bool
134
     */
135
    public function hasQueryParam(string $param): bool
136
    {
137
        return array_key_exists($param, $this->queryParameters);
138
    }
139
140
    /**
141
     * @param string $param
142
     *
143
     * @return mixed
144
     */
145
    public function getQueryParam(string $param)
146
    {
147
        if (!$this->hasQueryParam($param)) {
148
            throw new \InvalidArgumentException(sprintf('Invalid parameter "%s".', $param));
149
        }
150
151
        return $this->queryParameters[$param];
152
    }
153
154
    /**
155
     * @return Client
156
     */
157
    public function getClient(): Client
158
    {
159
        return $this->client;
160
    }
161
162
    /**
163
     * @param TokenType $tokenType
164
     *
165
     * @return Authorization
166
     */
167
    public function withTokenType(TokenType $tokenType): self
168
    {
169
        $clone = clone $this;
170
        $clone->tokenType = $tokenType;
171
172
        return $clone;
173
    }
174
175
    /**
176
     * @return null|TokenType
177
     */
178
    public function getTokenType(): ? TokenType
179
    {
180
        return $this->tokenType;
181
    }
182
183
    /**
184
     * @param ResponseType[] $responseTypes
185
     *
186
     * @return Authorization
187
     */
188
    public function withResponseTypes(array $responseTypes): self
189
    {
190
        $clone = clone $this;
191
        $clone->responseTypes = $responseTypes;
192
193
        return $clone;
194
    }
195
196
    /**
197
     * @return ResponseType[]
198
     */
199
    public function getResponseTypes(): array
200
    {
201
        return $this->responseTypes;
202
    }
203
204
    /**
205
     * @param ResponseMode $responseMode
206
     *
207
     * @return Authorization
208
     */
209
    public function withResponseMode(ResponseMode $responseMode): self
210
    {
211
        $clone = clone $this;
212
        $clone->responseMode = $responseMode;
213
214
        return $clone;
215
    }
216
217
    /**
218
     * @return null|ResponseMode
219
     */
220
    public function getResponseMode(): ? ResponseMode
221
    {
222
        return $this->responseMode;
223
    }
224
225
    /**
226
     * @param string $redirectUri
227
     *
228
     * @return Authorization
229
     */
230
    public function withRedirectUri(string $redirectUri): self
231
    {
232
        $clone = clone $this;
233
        $clone->redirectUri = $redirectUri;
234
235
        return $clone;
236
    }
237
238
    /**
239
     * @return null|string
240
     */
241
    public function getRedirectUri(): ? string
242
    {
243
        return $this->redirectUri;
244
    }
245
246
    /**
247
     * @param UserAccount $userAccount
248
     * @param bool        $isFullyAuthenticated
249
     *
250
     * @return Authorization
251
     */
252
    public function withUserAccount(UserAccount $userAccount, bool $isFullyAuthenticated): self
253
    {
254
        $clone = clone $this;
255
        $clone->userAccount = $userAccount;
256
        $clone->userAccountFullyAuthenticated = $isFullyAuthenticated;
257
258
        return $clone;
259
    }
260
261
    /**
262
     * @return null|UserAccount
263
     */
264
    public function getUserAccount(): ? UserAccount
265
    {
266
        return $this->userAccount;
267
    }
268
269
    /**
270
     * @param string $responseParameter
271
     * @param mixed  $value
272
     *
273
     * @return Authorization
274
     */
275
    public function withResponseParameter(string $responseParameter, $value): self
276
    {
277
        $clone = clone $this;
278
        $clone->responseParameters[$responseParameter] = $value;
279
280
        return $clone;
281
    }
282
283
    /**
284
     * @return array
285
     */
286
    public function getResponseParameters(): array
287
    {
288
        return $this->responseParameters;
289
    }
290
291
    /**
292
     * @param string $param
293
     *
294
     * @return mixed
295
     */
296
    public function getResponseParameter(string $param)
297
    {
298
        if (!$this->hasResponseParameter($param)) {
299
            throw new \InvalidArgumentException(sprintf('Invalid response parameter "%s".', $param));
300
        }
301
302
        return $this->getResponseParameters()[$param];
303
    }
304
305
    /**
306
     * @param string $param
307
     *
308
     * @return bool
309
     */
310
    public function hasResponseParameter(string $param): bool
311
    {
312
        return array_key_exists($param, $this->getResponseParameters());
313
    }
314
315
    /**
316
     * @param string $responseHeader
317
     * @param mixed  $value
318
     *
319
     * @return Authorization
320
     */
321
    public function withResponseHeader(string $responseHeader, $value): self
322
    {
323
        $clone = clone $this;
324
        $clone->responseHeaders[$responseHeader] = $value;
325
326
        return $clone;
327
    }
328
329
    /**
330
     * @return array
331
     */
332
    public function getResponseHeaders(): array
333
    {
334
        return $this->responseHeaders;
335
    }
336
337
    /**
338
     * @return bool|null
339
     */
340
    public function isUserAccountFullyAuthenticated(): ? bool
341
    {
342
        return $this->userAccountFullyAuthenticated;
343
    }
344
345
    /**
346
     * @return string[]
347
     */
348
    public function getPrompt(): array
349
    {
350
        if (!$this->hasQueryParam('prompt')) {
351
            return [];
352
        }
353
354
        return explode(' ', $this->getQueryParam('prompt'));
355
    }
356
357
    /**
358
     * @return bool
359
     */
360
    public function hasUiLocales(): bool
361
    {
362
        return $this->hasQueryParam('ui_locales');
363
    }
364
365
    /**
366
     * @return string[]
367
     */
368
    public function getUiLocales(): array
369
    {
370
        return $this->hasQueryParam('ui_locales') ? explode(' ', $this->getQueryParam('ui_locales')) : [];
371
    }
372
373
    /**
374
     * @param string $prompt
375
     *
376
     * @return bool
377
     */
378
    public function hasPrompt(string $prompt): bool
379
    {
380
        return in_array($prompt, $this->getPrompt());
381
    }
382
383
    /**
384
     * @param array $scope
385
     *
386
     * @return Authorization
387
     */
388
    public function withScopes(array $scope): self
389
    {
390
        $clone = clone $this;
391
        $clone->scopes = $scope;
392
393
        return $clone;
394
    }
395
396
    /**
397
     * @return array
398
     */
399
    public function getScopes(): array
400
    {
401
        return $this->scopes;
402
    }
403
404
    /**
405
     * @param string $scope
406
     *
407
     * @return bool
408
     */
409
    public function hasScope(string $scope): bool
410
    {
411
        return null !== $this->scopes && in_array($scope, $this->scopes);
412
    }
413
414
    /**
415
     * @param string $scope
416
     *
417
     * @return Authorization
418
     */
419
    public function withoutScope(string $scope): self
420
    {
421
        if (!$this->hasScope($scope)) {
422
            return $this;
423
        }
424
        $clone = clone $this;
425
        unset($clone->scopes[array_search($scope, $clone->scopes)]);
426
427
        return $clone;
428
    }
429
430
    /**
431
     * @param string $scope
432
     *
433
     * @return Authorization
434
     */
435
    public function addScope(string $scope): self
436
    {
437
        if ($this->hasScope($scope)) {
438
            return $this;
439
        }
440
        $clone = clone $this;
441
        $clone->scopes[] = $scope;
442
443
        return $clone;
444
    }
445
446
    /**
447
     * @return bool|null
448
     */
449
    public function isAuthorized(): ? bool
450
    {
451
        return $this->authorized;
452
    }
453
454
    /**
455
     * @return Authorization
456
     */
457
    public function allow(): self
458
    {
459
        $clone = clone $this;
460
        $clone->authorized = true;
461
462
        return $clone;
463
    }
464
465
    /**
466
     * @return Authorization
467
     */
468
    public function deny(): self
469
    {
470
        $clone = clone $this;
471
        $clone->authorized = false;
472
473
        return $clone;
474
    }
475
476
    /**
477
     * @param string $key
478
     *
479
     * @return bool
480
     */
481
    public function hasData(string $key): bool
482
    {
483
        return array_key_exists($key, $this->data);
484
    }
485
486
    /**
487
     * @param string $key
488
     *
489
     * @return mixed
490
     */
491
    public function getData(string $key)
492
    {
493
        if (!$this->hasData($key)) {
494
            throw new \InvalidArgumentException(sprintf('Invalid data "%s".', $key));
495
        }
496
497
        return $this->data[$key];
498
    }
499
500
    /**
501
     * @param string $key
502
     * @param mixed  $data
503
     *
504
     * @return Authorization
505
     */
506
    public function withData(string $key, $data): self
507
    {
508
        $clone = clone $this;
509
        $clone->data[$key] = $data;
510
511
        return $clone;
512
    }
513
514
    /**
515
     * @return null|ResourceServer
516
     */
517
    public function getResourceServer(): ? ResourceServer
518
    {
519
        return $this->resourceServer;
520
    }
521
522
    /**
523
     * @param ResourceServer $resourceServer
524
     *
525
     * @return Authorization
526
     */
527
    public function withResourceServer(ResourceServer $resourceServer): self
528
    {
529
        $clone = clone $this;
530
        $clone->resourceServer = $resourceServer;
531
532
        return $clone;
533
    }
534
535
    /**
536
     * @return bool
537
     */
538
    public function hasOfflineAccess(): bool
539
    {
540
        // The scope offline_access is not requested
541
        if (!in_array('offline_access', $this->getScopes())) {
542
            return false;
543
        }
544
545
        // The scope offline_access is requested but prompt is not consent
546
        // The scope offline_access is ignored
547
        if (!$this->hasQueryParam('prompt') || false === mb_strpos('consent', $this->getQueryParam('prompt'), 0, '8bit')) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !(!$this->hasQuer...'prompt'), 0, '8bit'));.
Loading history...
548
            return false;
549
        }
550
551
        return true;
552
    }
553
554
    /**
555
     * @param string $option
556
     * @param mixed  $value
557
     *
558
     * @return Authorization
559
     */
560
    public function withConsentScreenOption(string $option, $value): self
561
    {
562
        $clone = clone $this;
563
        $clone->consentScreenOptions[$option] = $value;
564
565
        return $clone;
566
    }
567
568
    /**
569
     * @param string $option
570
     *
571
     * @return Authorization
572
     */
573
    public function withoutConsentScreenOption(string $option): self
574
    {
575
        if (!array_key_exists($option, $this->consentScreenOptions)) {
576
            return $this;
577
        }
578
579
        $clone = clone $this;
580
        unset($clone->consentScreenOptions[$option]);
581
582
        return $clone;
583
    }
584
}
585