httpStatusCode = $httpStatusCode; $this->errorType = $errorType; $this->hint = $hint; $this->redirectUri = $redirectUri; } /** * Invalid grant type error * * @param null|string $localizedError * @param null|string $localizedHint * * @return static */ public static function invalidGrantType( $localizedError = null, $localizedHint = null ) { $errorMessage = (is_null($localizedError)) ? 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.' : $localizedError; $hint = (is_null($localizedHint)) ? 'Check the `grant_type` parameter' : $localizedHint; return new static($errorMessage, 'invalid_grant', 400, $hint); } /** * Unsupported grant type error * * @param null|string $localizedError * @param null|string $localizedHint * * @return static */ public static function unsupportedGrantType( $localizedError = null, $localizedHint = null ) { $errorMessage = (is_null($localizedError)) ? 'The authorization grant type is not supported by the authorization server.' : $localizedError; $hint = (is_null($localizedHint)) ? 'Check the `grant_type` parameter' : $localizedHint; return new static($errorMessage, 'unsupported_grant_type', 400, $hint); } /** * Invalid request error * * @param string $parameter The invalid parameter * @param null|string $localizedError * @param null|string $localizedHint * * @return static */ public static function invalidRequest( $parameter, $localizedError = null, $localizedHint = null ) { $errorMessage = (is_null($localizedError)) ? 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.' : $localizedError; $hint = (is_null($localizedHint)) ? sprintf('Check the `%s` parameter', $parameter) : sprintf($localizedHint, $parameter); return new static($errorMessage, 'invalid_request', 400, $hint); } /** * Invalid client error * * @param null|string $localizedError * * @return static */ public static function invalidClient($localizedError = null) { $errorMessage = (is_null($localizedError)) ? 'Client authentication failed' : $localizedError; return new static($errorMessage, 'invalid_client', 401); } /** * Invalid scope error * * @param string $scope The bad scope * @param null|string $localizedError A localized error message * @param null|string $localizedHint A localized error hint * @param null|string $redirectUri A HTTP URI to redirect the user back to * * @return static */ public static function invalidScope($scope, $localizedError = null, $localizedHint = null, $redirectUri = null) { $errorMessage = (is_null($localizedError)) ? 'The requested scope is invalid, unknown, or malformed' : $localizedError; $hint = (is_null($localizedHint)) ? sprintf('Check the `%s` scope', $scope) : sprintf($localizedHint, $scope); return new static($errorMessage, 'invalid_scope', 400, $hint, $redirectUri); } /** * Invalid credentials error * * @return static */ public static function invalidCredentials() { return new static('The user credentials were incorrect.', 'invalid_credentials', 401); } /** * Server error * * @param $hint * * @return static */ public static function serverError($hint) { return new static( 'The authorization server encountered an unexpected condition which prevented it from fulfilling' . 'the request.', 'server_error', 500, $hint ); } /** * Invalid refresh token * * @return static */ public static function invalidRefreshToken($hint = null) { return new static('The refresh token is invalid.', 'invalid_request', 400, $hint); } /** * Access denied * * @param null|string $hint * * @return static */ public static function accessDenied($hint = null) { return new static('The resource owner or authorization server denied the request.', 401, $hint); } /** * @return string */ public function getErrorType() { return $this->errorType; } /** * Generate a HTTP response * * @param \Psr\Http\Message\ResponseInterface $response * * @return \Psr\Http\Message\ResponseInterface */ public function generateHttpResponse(ResponseInterface $response = null) { if (!$response instanceof ResponseInterface) { $response = new Response(); } $headers = $this->getHttpHeaders(); $payload = [ 'error' => $this->errorType, 'message' => $this->getMessage() ]; if ($this->hint !== null) { $payload['hint'] = $this->hint; } if ($this->redirectUri !== null) { $headers['Location'] = RedirectUri::make($this->redirectUri, $payload); } foreach ($headers as $header => $content) { $response = $response->withHeader($header, $content); } return $response ->withStatus($this->getHttpStatusCode()) ->getBody()->write(json_encode($payload)); } /** * Get all headers that have to be send with the error response * * @return array Array with header values */ public function getHttpHeaders() { $headers = [ 'Content-type' => 'application/json' ]; // Add "WWW-Authenticate" header // // RFC 6749, section 5.2.: // "If the client attempted to authenticate via the 'Authorization' // request header field, the authorization server MUST // respond with an HTTP 401 (Unauthorized) status code and // include the "WWW-Authenticate" response header field // matching the authentication scheme used by the client. // @codeCoverageIgnoreStart if ($this->errorType === 'invalid_client') { $authScheme = null; $request = new ServerRequest(); if (isset($request->getServerParams()['PHP_AUTH_USER']) && $request->getServerParams()['PHP_AUTH_USER'] !== null ) { $authScheme = 'Basic'; } else { $authHeader = $request->getHeader('authorization'); if ($authHeader !== []) { if (strpos($authHeader[0], 'Bearer') === 0) { $authScheme = 'Bearer'; } elseif (strpos($authHeader[0], 'Basic') === 0) { $authScheme = 'Basic'; } } } if ($authScheme !== null) { $headers[] = 'WWW-Authenticate: ' . $authScheme . ' realm="OAuth"'; } } // @codeCoverageIgnoreEnd return $headers; } /** * Returns the HTTP status code to send when the exceptions is output * * @return int */ public function getHttpStatusCode() { return $this->httpStatusCode; } }