Passed
Push — master ( e88490...575397 )
by Alexandre
04:15
created

AuthorizationEndpoint::verifyResourceOwner()   C

Complexity

Conditions 8
Paths 8

Size

Total Lines 30
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 14
nc 8
nop 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Alexandre
5
 * Date: 18/02/2018
6
 * Time: 18:14
7
 */
8
9
namespace OAuth2\Extensions\OpenID\Endpoints;
10
11
12
use OAuth2\Exceptions\OAuthException;
13
use OAuth2\Extensions\OpenID\IdTokenManager;
14
use OAuth2\IdTokenInterface;
15
use OAuth2\ResponseModes\ResponseModeManager;
16
use OAuth2\ResponseTypes\ResponseTypeManager;
17
use OAuth2\Extensions\OpenID\Roles\ResourceOwnerInterface;
18
use OAuth2\ScopePolicy\ScopePolicyManager;
19
use OAuth2\Storages\ClientStorageInterface;
20
use Psr\Http\Message\ResponseInterface;
21
22
23
class AuthorizationEndpoint extends \OAuth2\Endpoints\AuthorizationEndpoint
24
{
25
    const DISPLAY_PAGE = 'page';
26
    const DISPLAY_POPUP = 'popup';
27
    const DISPLAY_TOUCH = 'touch';
28
    const DISPLAY_WAP = 'wap';
29
30
    const PROMPT_NONE = 'none';
31
    const PROMPT_LOGIN = 'login';
32
    const PROMPT_CONSENT = 'consent';
33
    const PROMPT_SELECT_ACCOUNT = 'select_account';
34
    /**
35
     * @var string|null
36
     */
37
    private $nonce;
38
    /**
39
     * @var string|null
40
     */
41
    private $display;
42
    /**
43
     * @var string|null
44
     */
45
    private $prompt;
46
    /**
47
     * @var int|null
48
     */
49
    private $maxAge;
50
    /**
51
     * @var string[]|null
52
     */
53
    private $uiLocales;
54
    /**
55
     * @var IdTokenInterface|null
56
     */
57
    private $idTokenHint;
58
    /**
59
     * @var string|null
60
     */
61
    private $loginHint;
62
    /**
63
     * @var string[]|null
64
     */
65
    private $acrValues;
66
    /**
67
     * @var ResourceOwnerInterface
68
     */
69
    private $resourceOwner;
70
    /**
71
     * @var IdTokenManager
72
     */
73
    private $idTokenManager;
74
75
    public function __construct(ResponseTypeManager $responseTypeManager, ResponseModeManager $responseModeManager,
76
                                ScopePolicyManager $scopePolicyManager, ResourceOwnerInterface $resourceOwner,
77
                                ClientStorageInterface $clientStorage, IdTokenManager $idTokenManager)
78
    {
79
        parent::__construct($responseTypeManager, $responseModeManager, $scopePolicyManager, $resourceOwner, $clientStorage);
80
        $this->resourceOwner = $resourceOwner;
81
        $this->idTokenManager = $idTokenManager;
82
    }
83
84
    /**
85
     * @return null|ResponseInterface
86
     * @throws OAuthException
87
     */
88
    protected function verifyResourceOwner(): ?ResponseInterface
89
    {
90
        if (!$this->resourceOwner->isAuthenticated(self::PROMPT_LOGIN)) {
0 ignored issues
show
Bug introduced by
self::PROMPT_LOGIN of type string is incompatible with the type boolean expected by parameter $alwaysAuthenticate of OAuth2\Extensions\OpenID...face::isAuthenticated(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

90
        if (!$this->resourceOwner->isAuthenticated(/** @scrutinizer ignore-type */ self::PROMPT_LOGIN)) {
Loading history...
91
            if ($this->prompt == self::PROMPT_NONE) {
92
                throw new OAuthException('login_required');
93
            }
94
95
            // may throw interaction_required
96
            return $this->resourceOwner->authenticate($this->prompt == self::PROMPT_SELECT_ACCOUNT, $this->loginHint);
97
        }
98
99
        if($this->idTokenHint) {
100
            // check if user associated to this id token is the current user.
101
//                var_dump($this->idTokenHint['sub']);die;
102
            if($this->idTokenHint['sub'] !== $this->resourceOwner->getIdentifier()) {
103
                if($this->prompt == self::PROMPT_NONE) {
104
                    throw new OAuthException('invalid_request');
105
                }
106
                else {
107
                    throw new OAuthException('login_required');
108
                }
109
            }
110
        }
111
112
        if ($this->prompt == self::PROMPT_NONE &&
113
            $this->resourceOwner->isInteractionRequiredForConsent($this)) {
114
            throw new OAuthException('interaction_required');
115
        }
116
117
        return null;
118
    }
119
120
    /**
121
     * @return null|ResponseInterface
122
     * @throws OAuthException
123
     */
124
    protected function verifyConsent(): ?ResponseInterface
125
    {
126
        $consentGiven = $this->resourceOwner->hasGivenConsent($this->getClient(), $this->getScopes(),
127
            $this->prompt == self::PROMPT_CONSENT);
128
129
        if (is_null($consentGiven)) {
130
            if ($this->prompt == self::PROMPT_NONE) {
131
                throw new OAuthException('consent_required');
132
            }
133
134
            return $this->resourceOwner->obtainConsent($this->getClient(), $this->getScopes());
135
        }
136
137
        if (empty($consentGiven)) {
138
            throw new OAuthException('access_denied', 'The resource owner denied the request.',
139
                'https://tools.ietf.org/html/rfc6749#section-4.1');
140
        }
141
142
        return null;
143
    }
144
145
    /**
146
     * @param array $requestData
147
     * @throws OAuthException
148
     */
149
    protected function verifyRequestData(array $requestData)
150
    {
151
        parent::verifyRequestData($requestData);
152
153
        if (!in_array('openid', $this->getScopes())) {
154
            return;
155
        }
156
157
        $this->nonce = empty($requestData['nonce']) ? null : $requestData['nonce'];
158
        $this->display = empty($requestData['display']) ? null : $requestData['display'];
159
        $this->prompt = empty($requestData['prompt']) ? null : $requestData['prompt'];
160
        $this->maxAge = empty($requestData['max_age']) ? null : $requestData['max_age'];
161
        $this->uiLocales = empty($requestData['ui_locales']) ? null : explode(' ', $requestData['ui_locales']);
162
163
        if(!empty($requestData['id_token_hint'])) {
164
            try {
165
                $this->idTokenHint = $this->idTokenManager->decode($requestData['id_token_hint']);
166
            } catch (\Exception $exception) {
167
                throw new OAuthException('invalid_request', 'Failed to decode id_token_hint : '.$exception->getMessage());
168
            }
169
        }
170
171
        $this->loginHint = empty($requestData['login_hint']) ? null : $requestData['login_hint'];
172
        $this->acrValues = empty($requestData['acr_values']) ? null : explode(' ', $requestData['acr_values']);
173
    }
174
175
    /**
176
     * @return ResourceOwnerInterface
177
     */
178
    public function getResourceOwner(): \OAuth2\Roles\ResourceOwnerInterface
179
    {
180
        return parent::getResourceOwner();
181
    }
182
183
    /**
184
     * @return string|null
185
     */
186
    public function getNonce(): ?string
187
    {
188
        return $this->nonce;
189
    }
190
191
    /**
192
     * @return null|string
193
     */
194
    public function getDisplay(): ?string
195
    {
196
        return $this->display;
197
    }
198
199
    /**
200
     * @return null|string
201
     */
202
    public function getPrompt(): ?string
203
    {
204
        return $this->prompt;
205
    }
206
207
    /**
208
     * @return int|null
209
     */
210
    public function getMaxAge(): ?int
211
    {
212
        return $this->maxAge;
213
    }
214
215
    /**
216
     * @return null|string[]
217
     */
218
    public function getUiLocales(): ?array
219
    {
220
        return $this->uiLocales;
221
    }
222
223
    /**
224
     * @return null|IdTokenInterface
225
     */
226
    public function getIdTokenHint(): ?IdTokenInterface
227
    {
228
        return $this->idTokenHint;
229
    }
230
231
    /**
232
     * @return null|string
233
     */
234
    public function getLoginHint(): ?string
235
    {
236
        return $this->loginHint;
237
    }
238
239
    /**
240
     * @return null|string[]
241
     */
242
    public function getAcrValues(): ?array
243
    {
244
        return $this->acrValues;
245
    }
246
}