Skip to content

AbstractProvider::getParsedResponse should always return array or throw exception #626

Open
@ksimka

Description

@ksimka
Uncaught Exception "TypeError" with message: "Argument 1 passed to League\OAuth2\Client\Provider\AbstractProvider::prepareAccessTokenResponse() must be of the type array, string given

It happens because AbstractProvider::getParsedResponse returns string when content can't be parsed.

  1. https://github.com/thephpleague/oauth2-client/blob/master/src/Provider/AbstractProvider.php#L528
// AbstractProvider::getAccessToken

// ...
$response = $this->getParsedResponse($request);
$prepared = $this->prepareAccessTokenResponse($response);
// ...
  1. https://github.com/thephpleague/oauth2-client/blob/master/src/Provider/AbstractProvider.php#L597
/**
     * Sends a request and returns the parsed response.
     *
     * @param  RequestInterface $request
     * @return mixed
     */
    public function getParsedResponse(RequestInterface $request)
    {
        try {
            $response = $this->getResponse($request);
        } catch (BadResponseException $e) {
            $response = $e->getResponse();
        }
        $parsed = $this->parseResponse($response);
        $this->checkResponse($response, $parsed);
        return $parsed;
    }

Attention to docs — "return mixed". It can not return "mixed" (though actually it is), because the result goes to prepareAccessTokenResponse which receives array only.

  1. https://github.com/thephpleague/oauth2-client/blob/master/src/Provider/AbstractProvider.php#L700
/**
     * Prepares an parsed access token response for a grant.
     *
     * Custom mapping of expiration, etc should be done here. Always call the
     * parent method when overloading this method.
     *
     * @param  mixed $result
     * @return array
     */
    protected function prepareAccessTokenResponse(array $result)

Docs say param mixed $result (was changed here 365e61c with no visible reason), but typehint says array $result.

And the last thing — where mixed comes from?

  1. https://github.com/thephpleague/oauth2-client/blob/master/src/Provider/AbstractProvider.php#L657
/**
     * Parses the response according to its content-type header.
     *
     * @throws UnexpectedValueException
     * @param  ResponseInterface $response
     * @return array
     */
    protected function parseResponse(ResponseInterface $response)
    {
        $content = (string) $response->getBody();
        $type = $this->getContentType($response);
        if (strpos($type, 'urlencoded') !== false) {
            parse_str($content, $parsed);
            return $parsed;
        }
        // Attempt to parse the string as JSON regardless of content type,
        // since some providers use non-standard content types. Only throw an
        // exception if the JSON could not be parsed when it was expected to.
        try {
            return $this->parseJson($content);
        } catch (UnexpectedValueException $e) {
            if (strpos($type, 'json') !== false) {
                throw $e;
            }
            return $content;
        }
    }

return array — one more lie here. Look at the catch block: value is considered unexpected only if type was "expected" — wut? Otherwise $content is returned, which is string. This was called fallback on failure.

So, long story short

  • provider returns some wierd response
  • oauth2-client tries to parse it as json and fails to
  • then the parse method returns a string (raw response body) instead of an exception or at least promised array
  • string goes to another method with array typehint
  • ???
  • TypeError (PHP 7)

I haven't done PR because I don't know what's the right solution in this situation. We should respect BC, I understand. But I'd just throw an exception despite any other condition: we tried to do something and failed — there is nothing we can do with it later.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions