Completed
Push — master ( 4a4f4f...599c9a )
by Alex
31:44
created

OAuthServerException::invalidGrant()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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