Passed
Pull Request — master (#1135)
by
unknown
11:19
created

RequestValidatorTrait::getBasicAuthCredentials()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 10
c 2
b 0
f 0
nc 5
nop 1
dl 0
loc 20
ccs 11
cts 11
cp 1
crap 5
rs 9.6111
1
<?php
2
/**
3
 * @author      Alex Bilbie <[email protected]>
4
 * @copyright   Copyright (c) Alex Bilbie
5
 * @license     http://mit-license.org/
6
 *
7
 * @link        https://github.com/thephpleague/oauth2-server
8
 */
9
10
namespace League\OAuth2\Server;
11
12
use League\OAuth2\Server\Entities\ClientEntityInterface;
13
use League\OAuth2\Server\Exception\OAuthServerException;
14
use Psr\Http\Message\ServerRequestInterface;
15
16
trait RequestValidatorTrait
17
{
18
    /**
19
     * Get the Emitter.
20
     *
21
     * @return \League\Event\EmitterInterface
22
     */
23
    abstract public function getEmitter();
24
25
    /**
26
     * @return \League\OAuth2\Server\Repositories\ClientRepositoryInterface
27
     */
28
    abstract public function getClientRepository();
29
30
    /**
31
     * Return the grant identifier that can be used in matching up requests.
32
     *
33
     * @return string
34
     */
35
    abstract public function getIdentifier();
36
37
    /**
38
     * Validate the client.
39
     *
40
     * @param ServerRequestInterface $request
41
     *
42
     * @throws OAuthServerException
43
     *
44
     * @return ClientEntityInterface
45
     */
46 53
    protected function validateClient(ServerRequestInterface $request)
47
    {
48 53
        list($clientId, $clientSecret) = $this->getClientCredentials($request);
49
50 51
        if ($this->clientRepository->validateClient($clientId, $clientSecret, $this->getIdentifier()) === false) {
51 5
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
52
53 5
            throw OAuthServerException::invalidClient($request);
54
        }
55
56 46
        $client = $this->getClientEntityOrFail($clientId, $request);
57
58
        // If a redirect URI is provided ensure it matches what is pre-registered
59 45
        $redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
60
61 45
        if ($redirectUri !== null) {
62 16
            $this->validateRedirectUri($redirectUri, $client, $request);
63
        }
64
65 43
        return $client;
66
    }
67
68
    /**
69
     * Wrapper around ClientRepository::getClientEntity() that ensures we emit
70
     * an event and throw an exception if the repo doesn't return a client
71
     * entity.
72
     *
73
     * This is a bit of defensive coding because the interface contract
74
     * doesn't actually enforce non-null returns/exception-on-no-client so
75
     * getClientEntity might return null. By contrast, this method will
76
     * always either return a ClientEntityInterface or throw.
77
     *
78
     * @param string                 $clientId
79
     * @param ServerRequestInterface $request
80
     *
81
     * @return ClientEntityInterface
82
     */
83 76
    protected function getClientEntityOrFail($clientId, ServerRequestInterface $request)
84
    {
85 76
        $client = $this->clientRepository->getClientEntity($clientId);
86
87 76
        if ($client instanceof ClientEntityInterface === false || empty($client->getRedirectUri())) {
88 6
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
89 6
            throw OAuthServerException::invalidClient($request);
90
        }
91
92 70
        return $client;
93
    }
94
95
    /**
96
     * Validate redirectUri from the request.
97
     * If a redirect URI is provided ensure it matches what is pre-registered
98
     *
99
     * @param string                 $redirectUri
100
     * @param ClientEntityInterface  $client
101
     * @param ServerRequestInterface $request
102
     *
103
     * @throws OAuthServerException
104
     */
105 31
    protected function validateRedirectUri(
106
        string $redirectUri,
107
        ClientEntityInterface $client,
108
        ServerRequestInterface $request
109
    ) {
110 31
        if (\is_string($client->getRedirectUri())
111 31
            && (\strcmp($client->getRedirectUri(), $redirectUri) !== 0)
112
        ) {
113 3
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
114 3
            throw OAuthServerException::invalidClient($request);
115 28
        } elseif (\is_array($client->getRedirectUri())
116 28
            && \in_array($redirectUri, $client->getRedirectUri(), true) === false
117
        ) {
118 3
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
119 3
            throw OAuthServerException::invalidClient($request);
120
        }
121 25
    }
122
123
    /**
124
     * Gets the client credentials from the request from the request body or
125
     * the Http Basic Authorization header
126
     *
127
     * @param ServerRequestInterface $request
128
     *
129
     * @return array
130
     */
131 62
    protected function getClientCredentials(ServerRequestInterface $request)
132
    {
133 62
        list($basicAuthUser, $basicAuthPassword) = $this->getBasicAuthCredentials($request);
134
135 62
        $clientId = $this->getRequestParameter('client_id', $request, $basicAuthUser);
136
137 62
        if (\is_null($clientId)) {
138 2
            throw OAuthServerException::invalidRequest('client_id');
139
        }
140
141 60
        $clientSecret = $this->getRequestParameter('client_secret', $request, $basicAuthPassword);
142
143 60
        return [$clientId, $clientSecret];
144
    }
145
146
    /**
147
     * Retrieve request parameter.
148
     *
149
     * @param string                 $parameter
150
     * @param ServerRequestInterface $request
151
     * @param mixed                  $default
152
     *
153
     * @return null|string
154
     */
155 62
    protected function getRequestParameter($parameter, ServerRequestInterface $request, $default = null)
156
    {
157 62
        $requestParameters = (array) $request->getParsedBody();
158
159 62
        return $requestParameters[$parameter] ?? $default;
160
    }
161
162
    /**
163
     * Retrieve HTTP Basic Auth credentials with the Authorization header
164
     * of a request. First index of the returned array is the username,
165
     * second is the password (so list() will work). If the header does
166
     * not exist, or is otherwise an invalid HTTP Basic header, return
167
     * [null, null].
168
     *
169
     * @param ServerRequestInterface $request
170
     *
171
     * @return string[]|null[]
172
     */
173 67
    protected function getBasicAuthCredentials(ServerRequestInterface $request)
174
    {
175 67
        if (!$request->hasHeader('Authorization')) {
176 60
            return [null, null];
177
        }
178
179 7
        $header = $request->getHeader('Authorization')[0];
180 7
        if (\strpos($header, 'Basic ') !== 0) {
181 1
            return [null, null];
182
        }
183
184 6
        if (!($decoded = \base64_decode(\substr($header, 6)))) {
185 1
            return [null, null];
186
        }
187
188 5
        if (\strpos($decoded, ':') === false) {
189 2
            return [null, null]; // HTTP Basic header without colon isn't valid
190
        }
191
192 3
        return \explode(':', $decoded, 2);
193
    }
194
195
    /**
196
     * Retrieve query string parameter.
197
     *
198
     * @param string                 $parameter
199
     * @param ServerRequestInterface $request
200
     * @param mixed                  $default
201
     *
202
     * @return null|string
203
     */
204 24
    protected function getQueryStringParameter($parameter, ServerRequestInterface $request, $default = null)
205
    {
206 24
        return isset($request->getQueryParams()[$parameter]) ? $request->getQueryParams()[$parameter] : $default;
207
    }
208
209
    /**
210
     * Retrieve cookie parameter.
211
     *
212
     * @param string                 $parameter
213
     * @param ServerRequestInterface $request
214
     * @param mixed                  $default
215
     *
216
     * @return null|string
217
     */
218 1
    protected function getCookieParameter($parameter, ServerRequestInterface $request, $default = null)
219
    {
220 1
        return isset($request->getCookieParams()[$parameter]) ? $request->getCookieParams()[$parameter] : $default;
221
    }
222
223
    /**
224
     * Retrieve server parameter.
225
     *
226
     * @param string                 $parameter
227
     * @param ServerRequestInterface $request
228
     * @param mixed                  $default
229
     *
230
     * @return null|string
231
     */
232 23
    protected function getServerParameter($parameter, ServerRequestInterface $request, $default = null)
233
    {
234 23
        return isset($request->getServerParams()[$parameter]) ? $request->getServerParams()[$parameter] : $default;
235
    }
236
}
237