AuthorizationRequestBuilder::getResponseMode()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 6
nop 2
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Alexandre
5
 * Date: 24/05/2018
6
 * Time: 22:06
7
 */
8
9
namespace OAuth2\Endpoints\Authorization;
10
11
12
use GuzzleHttp\Psr7\Uri;
13
use OAuth2\AuthorizationEndpointResponseTypes\ResponseTypeInterface;
14
use OAuth2\AuthorizationEndpointResponseTypes\ResponseTypeManager;
15
use OAuth2\Exceptions\InvalidAuthorizationRequest;
16
use OAuth2\Exceptions\InvalidRequestMethod;
17
use OAuth2\Exceptions\OAuthException;
18
use OAuth2\ResponseModes\ResponseModeInterface;
19
use OAuth2\ResponseModes\ResponseModeManager;
20
use OAuth2\Roles\ClientTypes\ConfidentialClientInterface;
21
use OAuth2\Roles\ClientTypes\PublicClientInterface;
22
use OAuth2\Roles\ClientTypes\RegisteredClient;
23
use OAuth2\Roles\ResourceOwnerInterface;
24
use OAuth2\ScopePolicy\ScopePolicyManager;
25
use OAuth2\Storages\ClientStorageInterface;
26
use Psr\Http\Message\ServerRequestInterface;
27
28
29
class AuthorizationRequestBuilder
30
{
31
    /**
32
     * @var ClientStorageInterface
33
     */
34
    protected $clientStorage;
35
    /**
36
     * @var ResponseTypeManager
37
     */
38
    protected $responseTypeManager;
39
    /**
40
     * @var ResponseModeManager
41
     */
42
    protected $responseModeManager;
43
    /**
44
     * @var ScopePolicyManager
45
     */
46
    protected $scopePolicyManager;
47
48
    public function __construct(ClientStorageInterface $clientStorage,
49
                                ResponseTypeManager $responseTypeManager,
50
                                ResponseModeManager $responseModeManager,
51
                                ScopePolicyManager $scopePolicyManager)
52
    {
53
        $this->clientStorage = $clientStorage;
54
        $this->responseTypeManager = $responseTypeManager;
55
        $this->responseModeManager = $responseModeManager;
56
        $this->scopePolicyManager = $scopePolicyManager;
57
    }
58
59
    /**
60
     * @param ServerRequestInterface $request
61
     * @param ResourceOwnerInterface $resourceOwner
62
     * @return AuthorizationRequestInterface
63
     * @throws InvalidRequestMethod
64
     * @throws OAuthException
65
     * @throws InvalidAuthorizationRequest
66
     */
67
    public function build(ServerRequestInterface $request, ResourceOwnerInterface $resourceOwner): AuthorizationRequestInterface
68
    {
69
        if ($request->getMethod() === 'GET') {
70
            $data = $request->getQueryParams();
71
        } else if ($request->getMethod() === 'POST') {
72
            $data = is_array($request->getParsedBody()) ? $request->getParsedBody() : [];
73
        } else {
74
            throw new InvalidRequestMethod();
75
        }
76
77
        $client = $this->getClient($data['client_id'] ?? null);
78
79
        $responseType = $this->getResponseType($client, $data['response_type'] ?? null);
80
        $redirectUri = $this->getRedirectUri($client, $responseType, $data['redirect_uri'] ?? null);
81
        $responseMode = $this->getResponseMode($responseType, $data['response_mode'] ?? null);
82
        $state = $requestData['state'] ?? null;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $requestData does not exist. Did you maybe mean $request?
Loading history...
83
84
        try {
85
            $requestedScopes = $this->scopePolicyManager->scopeStringToArray($data['scope'] ?? null);
86
            $scopes = $this->scopePolicyManager->getScopes($client, $requestedScopes);
87
        } catch (OAuthException $e) {
88
            throw new InvalidAuthorizationRequest($e, $redirectUri, $responseMode, $state);
89
        }
90
91
        return new AuthorizationRequest($data, $resourceOwner, $client, $redirectUri, $responseType, $responseMode,
92
            $scopes, $requestedScopes, $state);
93
    }
94
95
    /**
96
     * @param null|string $clientIdentifier
97
     * @return RegisteredClient
98
     * @throws OAuthException
99
     */
100
    protected function getClient(?string $clientIdentifier): RegisteredClient
101
    {
102
        if (empty($clientIdentifier)) {
103
            throw new OAuthException('invalid_request', 'The request is missing the required parameter client_id.',
104
                'https://tools.ietf.org/html/rfc6749#section-4.1');
105
        }
106
107
        if (!($client = $this->clientStorage->get($clientIdentifier))) {
108
            throw new OAuthException('invalid_request', 'The request includes the invalid parameter client_id.',
109
                'https://tools.ietf.org/html/rfc6749#section-4.1');
110
        }
111
112
        return $client;
113
    }
114
115
    protected function isRedirectUriRegistrationRequired(RegisteredClient $client, ResponseTypeInterface $responseType)
116
    {
117
        if ($client instanceof PublicClientInterface ||
118
            ($client instanceof ConfidentialClientInterface && $responseType->isRegistrationOfRedirectUriRequired())) {
119
            return true;
120
        }
121
        return false;
122
    }
123
124
    /**
125
     * @param RegisteredClient $client
126
     * @param ResponseTypeInterface $responseType
127
     * @return array|null
128
     * @throws OAuthException
129
     */
130
    protected function getRegisteredRedirectUris(RegisteredClient $client, ResponseTypeInterface $responseType)
131
    {
132
        $redirectUris = $client->getMetadata()->getRedirectUris();
133
134
        if (empty($redirectUris) && $this->isRedirectUriRegistrationRequired($client, $responseType)) {
135
            throw new OAuthException('invalid_request',
136
                'Clients using flows with redirection MUST register their redirection URI values',
137
                'https://tools.ietf.org/html/rfc7591#section-2.1');
138
        }
139
140
        return $redirectUris;
141
    }
142
143
    /**
144
     * @param RegisteredClient $client
145
     * @param ResponseTypeInterface $responseType
146
     * @param null|string $requestRedirectUri
147
     * @return Uri
148
     * @throws OAuthException
149
     */
150
    protected function getRedirectUri(RegisteredClient $client, ResponseTypeInterface $responseType,
151
                                      ?string $requestRedirectUri = null)
152
    {
153
        $registeredRedirectUris = $this->getRegisteredRedirectUris($client, $responseType);
154
155
        if (!$requestRedirectUri) {
156
            if (count($registeredRedirectUris) != 1) {
157
                throw new OAuthException('invalid_request',
158
                    'The request is missing the required parameter redirect_uri.',
159
                    'https://tools.ietf.org/html/rfc6749#section-4.1');
160
            }
161
162
            $requestRedirectUri = $registeredRedirectUris[0];
163
        } else if (!empty($registeredRedirectUris) && !in_array($requestRedirectUri, $registeredRedirectUris)) {
164
            throw new OAuthException('invalid_request',
165
                'The request is missing the required parameter redirect_uri.',
166
                'https://tools.ietf.org/html/rfc6749#section-4.1');
167
        }
168
169
        try {
170
            $redirectUri = new Uri($requestRedirectUri);
171
            if ($redirectUri->getFragment()) {
172
                throw new \InvalidArgumentException('The endpoint URI must not include a fragment component.');
173
            }
174
        } catch (\InvalidArgumentException $e) {
175
            throw new OAuthException('invalid_request',
176
                'The request includes the malformed parameter redirect_uri. ' . $e->getMessage(),
177
                'https://tools.ietf.org/html/rfc6749#section-4.1');
178
        }
179
180
        return $redirectUri;
181
    }
182
183
    /**
184
     * @param RegisteredClient $client
185
     * @param null|string $requestResponseType
186
     * @return ResponseTypeInterface
187
     * @throws OAuthException
188
     */
189
    protected function getResponseType(RegisteredClient $client, ?string $requestResponseType = null): ResponseTypeInterface
190
    {
191
        if (empty($requestResponseType)) {
192
            throw new OAuthException('invalid_request',
193
                'The request is missing the required parameter response_type.',
194
                'https://tools.ietf.org/html/rfc6749#section-4.1');
195
        }
196
197
        if (!($responseType = $this->responseTypeManager->getResponseType($requestResponseType))) {
198
            throw new OAuthException('invalid_request',
199
                'The request includes the invalid parameter response_type.',
200
                'https://tools.ietf.org/html/rfc6749#section-4.1');
201
        }
202
203
        $supportedResponseTypes = $client->getMetadata()->getResponseTypes() ?: ['code'];
204
        foreach (explode(' ', $requestResponseType) as $type) {
205
            if (!in_array($type, $supportedResponseTypes)) {
206
                throw new OAuthException('unsupported_response_type',
207
                    'The authorization server does not support obtaining an authorization code using this method.',
208
                    'https://tools.ietf.org/html/rfc6749#section-4.1');
209
            }
210
        }
211
212
        return $responseType;
213
    }
214
215
    /**
216
     * @param ResponseTypeInterface $responseType
217
     * @param null|string $requestResponseMode
218
     * @return ResponseModeInterface
219
     * @throws OAuthException
220
     */
221
    protected function getResponseMode(ResponseTypeInterface $responseType, ?string $requestResponseMode = null): ResponseModeInterface
222
    {
223
        $responseModeIdentifier = $responseType->getDefaultResponseMode();
224
        if (!empty($requestResponseMode)) {
225
            $responseModeIdentifier = $requestResponseMode;
226
        }
227
228
        if (!($responseMode = $this->responseModeManager->getResponseMode($responseModeIdentifier))) {
229
            throw new OAuthException('invalid_request', 'response_mode invalid');
230
        }
231
232
        if (in_array($responseModeIdentifier, $responseType->getUnsupportedResponseModes())) {
233
            throw new OAuthException('invalid_request', 'response_mode unsupported');
234
        }
235
236
        return $responseMode;
237
    }
238
}