Completed
Push — master ( 3098f6...fea577 )
by Andrew
154:01 queued 119:03
created

OAuthServerException::setPayload()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
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\Exception;
11
12
use Psr\Http\Message\ResponseInterface;
13
14
class OAuthServerException extends \Exception
15
{
16
    /**
17
     * @var int
18
     */
19
    private $httpStatusCode;
20
21
    /**
22
     * @var string
23
     */
24
    private $errorType;
25
26
    /**
27
     * @var null|string
28
     */
29
    private $hint;
30
31
    /**
32
     * @var null|string
33
     */
34
    private $redirectUri;
35
36
    /**
37
     * @var  array
38
     */
39
    private $payload;
40
41
    /**
42
     * Throw a new exception.
43
     *
44
     * @param string      $message        Error message
45
     * @param int         $code           Error code
46
     * @param string      $errorType      Error type
47
     * @param int         $httpStatusCode HTTP status code to send (default = 400)
48
     * @param null|string $hint           A helper hint
49
     * @param null|string $redirectUri    A HTTP URI to redirect the user back to
50
     */
51
    public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null)
52
    {
53
        parent::__construct($message, $code);
54
        $this->httpStatusCode = $httpStatusCode;
55
        $this->errorType = $errorType;
56
        $this->hint = $hint;
57
        $this->redirectUri = $redirectUri;
58
        $this->payload = [
59
            'error'   => $errorType,
60
            'message' => $message,
61
        ];
62
        if ($hint !== null) {
63
            $this->payload['hint'] = $hint;
64
        }
65
    }
66
67
    /**
68
     * Returns the current payload.
69
     *
70
     * @return array
71
     */
72
    public function getPayload()
73
    {
74
        return $this->payload;
75
    }
76
77
    /**
78
     * Updates the current payload.
79
     *
80
     * @param array $payload
81
     */
82
    public function setPayload(array $payload)
83
    {
84
        $this->payload = $payload;
85
    }
86
87
    /**
88
     * Unsupported grant type error.
89
     *
90
     * @return static
91
     */
92
    public static function unsupportedGrantType()
93
    {
94
        $errorMessage = 'The authorization grant type is not supported by the authorization server.';
95
        $hint = 'Check the `grant_type` parameter';
96
97
        return new static($errorMessage, 2, 'unsupported_grant_type', 400, $hint);
98
    }
99
100
    /**
101
     * Invalid request error.
102
     *
103
     * @param string      $parameter The invalid parameter
104
     * @param null|string $hint
105
     *
106
     * @return static
107
     */
108
    public static function invalidRequest($parameter, $hint = null)
109
    {
110
        $errorMessage = 'The request is missing a required parameter, includes an invalid parameter value, ' .
111
            'includes a parameter more than once, or is otherwise malformed.';
112
        $hint = ($hint === null) ? sprintf('Check the `%s` parameter', $parameter) : $hint;
113
114
        return new static($errorMessage, 3, 'invalid_request', 400, $hint);
115
    }
116
117
    /**
118
     * Invalid client error.
119
     *
120
     * @return static
121
     */
122
    public static function invalidClient()
123
    {
124
        $errorMessage = 'Client authentication failed';
125
126
        return new static($errorMessage, 4, 'invalid_client', 401);
127
    }
128
129
    /**
130
     * Invalid scope error.
131
     *
132
     * @param string      $scope       The bad scope
133
     * @param null|string $redirectUri A HTTP URI to redirect the user back to
134
     *
135
     * @return static
136
     */
137
    public static function invalidScope($scope, $redirectUri = null)
138
    {
139
        $errorMessage = 'The requested scope is invalid, unknown, or malformed';
140
141
        if (empty($scope)) {
142
            $hint = 'Specify a scope in the request or set a default scope';
143
        } else {
144
            $hint = sprintf(
145
                'Check the `%s` scope',
146
                htmlspecialchars($scope, ENT_QUOTES, 'UTF-8', false)
147
            );
148
        }
149
150
        return new static($errorMessage, 5, 'invalid_scope', 400, $hint, $redirectUri);
151
    }
152
153
    /**
154
     * Invalid credentials error.
155
     *
156
     * @return static
157
     */
158
    public static function invalidCredentials()
159
    {
160
        return new static('The user credentials were incorrect.', 6, 'invalid_credentials', 401);
161
    }
162
163
    /**
164
     * Server error.
165
     *
166
     * @param string $hint
167
     *
168
     * @return static
169
     *
170
     * @codeCoverageIgnore
171
     */
172
    public static function serverError($hint)
173
    {
174
        return new static(
175
            'The authorization server encountered an unexpected condition which prevented it from fulfilling'
176
            . ' the request: ' . $hint,
177
            7,
178
            'server_error',
179
            500
180
        );
181
    }
182
183
    /**
184
     * Invalid refresh token.
185
     *
186
     * @param null|string $hint
187
     *
188
     * @return static
189
     */
190
    public static function invalidRefreshToken($hint = null)
191
    {
192
        return new static('The refresh token is invalid.', 8, 'invalid_request', 401, $hint);
193
    }
194
195
    /**
196
     * Access denied.
197
     *
198
     * @param null|string $hint
199
     * @param null|string $redirectUri
200
     *
201
     * @return static
202
     */
203
    public static function accessDenied($hint = null, $redirectUri = null)
204
    {
205
        return new static(
206
            'The resource owner or authorization server denied the request.',
207
            9,
208
            'access_denied',
209
            401,
210
            $hint,
211
            $redirectUri
212
        );
213
    }
214
215
    /**
216
     * Invalid grant.
217
     *
218
     * @param string $hint
219
     *
220
     * @return static
221
     */
222
    public static function invalidGrant($hint = '')
223
    {
224
        return new static(
225
            'The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token '
226
                . 'is invalid, expired, revoked, does not match the redirection URI used in the authorization request, '
227
                . 'or was issued to another client.',
228
            10,
229
            'invalid_grant',
230
            400,
231
            $hint
232
        );
233
    }
234
235
    /**
236
     * @return string
237
     */
238
    public function getErrorType()
239
    {
240
        return $this->errorType;
241
    }
242
243
    /**
244
     * Generate a HTTP response.
245
     *
246
     * @param ResponseInterface $response
247
     * @param bool              $useFragment True if errors should be in the URI fragment instead of query string
248
     * @param int                $jsonOptions options passed to json_encode
249
     *
250
     * @return ResponseInterface
251
     */
252
    public function generateHttpResponse(ResponseInterface $response, $useFragment = false, $jsonOptions = 0)
253
    {
254
        $headers = $this->getHttpHeaders();
255
256
        $payload = $this->getPayload();
257
258
        if ($this->redirectUri !== null) {
259
            if ($useFragment === true) {
260
                $this->redirectUri .= (strstr($this->redirectUri, '#') === false) ? '#' : '&';
261
            } else {
262
                $this->redirectUri .= (strstr($this->redirectUri, '?') === false) ? '?' : '&';
263
            }
264
265
            return $response->withStatus(302)->withHeader('Location', $this->redirectUri . http_build_query($payload));
266
        }
267
268
        foreach ($headers as $header => $content) {
269
            $response = $response->withHeader($header, $content);
270
        }
271
272
        $response->getBody()->write(json_encode($payload, $jsonOptions));
273
274
        return $response->withStatus($this->getHttpStatusCode());
275
    }
276
277
    /**
278
     * Get all headers that have to be send with the error response.
279
     *
280
     * @return array Array with header values
281
     */
282
    public function getHttpHeaders()
0 ignored issues
show
Coding Style introduced by
getHttpHeaders uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
283
    {
284
        $headers = [
285
            'Content-type' => 'application/json',
286
        ];
287
288
        // Add "WWW-Authenticate" header
289
        //
290
        // RFC 6749, section 5.2.:
291
        // "If the client attempted to authenticate via the 'Authorization'
292
        // request header field, the authorization server MUST
293
        // respond with an HTTP 401 (Unauthorized) status code and
294
        // include the "WWW-Authenticate" response header field
295
        // matching the authentication scheme used by the client.
296
        // @codeCoverageIgnoreStart
297
        if ($this->errorType === 'invalid_client') {
298
            $authScheme = 'Basic';
299
            if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER) !== false
300
                && strpos($_SERVER['HTTP_AUTHORIZATION'], 'Bearer') === 0
301
            ) {
302
                $authScheme = 'Bearer';
303
            }
304
            $headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"';
305
        }
306
        // @codeCoverageIgnoreEnd
307
        return $headers;
308
    }
309
310
    /**
311
     * Returns the HTTP status code to send when the exceptions is output.
312
     *
313
     * @return int
314
     */
315
    public function getHttpStatusCode()
316
    {
317
        return $this->httpStatusCode;
318
    }
319
320
    /**
321
     * @return null|string
322
     */
323
    public function getHint()
324
    {
325
        return $this->hint;
326
    }
327
}
328