Failed Conditions
Push — master ( 5cdde8...0d92d9 )
by Florent
04:33
created

UserInfo::computeClaimWithLocale()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 2
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\OpenIdConnect\UserInfo;
15
16
use OAuth2Framework\Component\OpenIdConnect\UserInfo\Claim\ClaimManager;
17
use OAuth2Framework\Component\OpenIdConnect\UserInfo\Claim\ClaimSourceManager;
18
use OAuth2Framework\Component\OpenIdConnect\UserInfo\Pairwise\PairwiseSubjectIdentifierAlgorithm;
19
use OAuth2Framework\Component\OpenIdConnect\UserInfo\ScopeSupport\UserInfoScopeSupportManager;
20
use OAuth2Framework\Component\Core\Client\Client;
21
use OAuth2Framework\Component\Core\UserAccount\UserAccount;
22
23
class UserInfo
24
{
25
    /**
26
     * @var null|PairwiseSubjectIdentifierAlgorithm
27
     */
28
    private $pairwiseAlgorithm = null;
29
30
    /**
31
     * @var UserInfoScopeSupportManager
32
     */
33
    private $userinfoScopeSupportManager;
34
35
    /**
36
     * @var ClaimSourceManager
37
     */
38
    private $claimSourceManager;
39
40
    /**
41
     * @var ClaimManager
42
     */
43
    private $claimManager;
44
45
    /**
46
     * UserInfo constructor.
47
     *
48
     * @param UserInfoScopeSupportManager $userinfoScopeSupportManager
49
     * @param ClaimManager                $claimManager
50
     * @param ClaimSourceManager          $claimSourceManager
51
     */
52
    public function __construct(UserInfoScopeSupportManager $userinfoScopeSupportManager, ClaimManager $claimManager, ClaimSourceManager $claimSourceManager)
53
    {
54
        $this->userinfoScopeSupportManager = $userinfoScopeSupportManager;
55
        $this->claimManager = $claimManager;
56
        $this->claimSourceManager = $claimSourceManager;
57
    }
58
59
    /**
60
     * @param Client      $client
61
     * @param UserAccount $userAccount
62
     * @param string      $redirectUri
63
     * @param array       $requestedClaims
64
     * @param string      $scope
65
     * @param string|null $claimsLocales
66
     *
67
     * @return array
68
     */
69
    public function getUserinfo(Client $client, UserAccount $userAccount, string $redirectUri, array $requestedClaims, string $scope, ? string $claimsLocales): array
70
    {
71
        $requestedClaims = array_merge(
72
            $this->getClaimsFromClaimScope($scope),
73
            $requestedClaims
74
        );
75
        $claims = $this->getClaimValues($userAccount, $requestedClaims, $claimsLocales);
76
        /*$claims = array_merge(
0 ignored issues
show
Unused Code Comprehensibility introduced by
61% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
77
            $claims,
78
            $this->claimSourceManager->getUserInfo($userAccount, $scope, [])
79
        );*/
80
        $claims['sub'] = $this->calculateSubjectIdentifier($client, $userAccount, $redirectUri);
81
82
        return $claims;
83
    }
84
85
    /**
86
     * @param string $scope
87
     *
88
     * @return array
89
     */
90
    private function getClaimsFromClaimScope(string $scope): array
91
    {
92
        $result = [];
93
94
        foreach (explode(' ', $scope) as $scp) {
95
            if ($this->userinfoScopeSupportManager->has($scp)) {
96
                $scope_claims = $this->userinfoScopeSupportManager->get($scp)->getAssociatedClaims();
97
                foreach ($scope_claims as $scope_claim) {
98
                    $result[$scope_claim] = null;
99
                }
100
            }
101
        }
102
103
        return $result;
104
    }
105
106
    /**
107
     * @param UserAccount $userAccount
108
     * @param string|null $claimsLocales
109
     * @param array       $requestedClaims
110
     *
111
     * @return array
112
     */
113
    private function getClaimValues(UserAccount $userAccount, array $requestedClaims, ?string $claimsLocales): array
114
    {
115
        $result = [];
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
116
        if (null === $claimsLocales) {
117
            $claimsLocales = [];
118
        } elseif (true === is_string($claimsLocales)) {
119
            $claimsLocales = array_unique(explode(' ', $claimsLocales));
120
        }
121
        $result = $this->claimManager->getUserInfo($userAccount, $requestedClaims, $claimsLocales);
122
        /*foreach ($requestedClaims as $claim => $config) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
123
            foreach ($claimsLocales as $claims_locale) {
124
                $claim_locale = $this->computeClaimWithLocale($claim, $claims_locale);
125
                $claim_value = $this->getUserClaim($userAccount, $claim_locale, $config);
126
                if (null !== $claim_value) {
127
                    $result[$claim_locale] = $claim_value;
128
129
                    break;
130
                }
131
            }
132
        }*/
133
134
        return $result;
135
    }
136
137
    /**
138
     * @param UserAccount $userAccount
139
     * @param string      $claimName
140
     * @param null|array  $config
141
     *
142
     * @return null|mixed
143
     */
144
    private function getUserClaim(UserAccount $userAccount, string $claimName, ?array $config)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
145
    {
146
        // FIXME: "acr" claim support has to be added.
147
        if ($userAccount->has($claimName)) {
148
            $claim = $userAccount->get($claimName);
149
            switch (true) {
150
                case is_array($config) && array_key_exists('value', $config):
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
151
                    if ($claim === $config['value']) {
152
                        return $claim;
153
                    }
154
155
                    break;
156
                case is_array($config) && array_key_exists('values', $config) && is_array($config['values']):
157
                    if (in_array($claim, $config['values'])) {
158
                        return $claim;
159
                    }
160
161
                    break;
162
                default:
163
                    return $claim;
164
            }
165
        }
166
167
        return null;
168
    }
169
170
    /**
171
     * @param PairwiseSubjectIdentifierAlgorithm $pairwiseAlgorithm
172
     */
173
    public function enablePairwiseSubject(PairwiseSubjectIdentifierAlgorithm $pairwiseAlgorithm)
174
    {
175
        $this->pairwiseAlgorithm = $pairwiseAlgorithm;
176
    }
177
178
    /**
179
     * @return bool
180
     */
181
    public function isPairwiseSubjectIdentifierSupported(): bool
182
    {
183
        return null !== $this->pairwiseAlgorithm;
184
    }
185
186
    /**
187
     * @return PairwiseSubjectIdentifierAlgorithm|null
188
     */
189
    public function getPairwiseSubjectIdentifierAlgorithm(): ? PairwiseSubjectIdentifierAlgorithm
190
    {
191
        return $this->pairwiseAlgorithm;
192
    }
193
194
    /**
195
     * @param Client      $client
196
     * @param UserAccount $userAccount
197
     * @param string      $redirectUri
198
     *
199
     * @return string
200
     */
201
    private function calculateSubjectIdentifier(Client $client, UserAccount $userAccount, string $redirectUri): string
202
    {
203
        $sub = $userAccount->getUserAccountId()->getValue();
204
        if (false === $this->isPairwiseSubjectIdentifierSupported()) {
205
            return $sub;
206
        }
207
        if (($client->has('subject_type') && ('pairwise' === $client->get('subject_type')))) {
208
            $sectorIdentifierHost = $this->getSectorIdentifierHost($client, $redirectUri);
209
210
            return $this->pairwiseAlgorithm->calculateSubjectIdentifier(
211
                $userAccount,
212
                $sectorIdentifierHost
213
            );
214
        }
215
216
        return $sub;
217
    }
218
219
    /**
220
     * @param Client $client
221
     * @param string $redirectUri
222
     *
223
     * @return string
224
     */
225
    private function getSectorIdentifierHost(Client $client, string $redirectUri): string
226
    {
227
        $uri = $redirectUri;
228
229
        if (true === $client->has('sector_identifier_uri')) {
230
            $uri = $client->get('sector_identifier_uri');
231
        }
232
233
        $data = parse_url($uri);
234
        if (!is_array($data) || !array_key_exists('host', $data)) {
235
            throw new \InvalidArgumentException(sprintf('Invalid Sector Identifier Uri "%s".', $uri));
236
        }
237
238
        return $data['host'];
239
    }
240
}
241