protected function parseAuthorizationRequest(IRequest $request, IUser $user)
    {
        $clientId = $request->query('client_id');

        if (!$clientId) {
            throw new InvalidRequestException('Client id is missing.');
        }

        $client = $this->clientStorage->get($clientId);

        if (!$client) {
            throw new InvalidClientException('Invalid client.');
        }

        if (!$client->isAllowedToUse($this)) {
            throw new UnauthorizedClientException('Client can not use this grant type.');
        }

        $redirectUri = $request->query('redirect_uri');
        $clientRedirectUri = $client->getRedirectUri();

        if ($redirectUri) {
            $parsedUrl = parse_url($redirectUri);

            if ($parsedUrl === false || isset($parsedUrl['fragment'])) {
                throw new InvalidRequestException('Redirect URI is invalid.');
            }

            if (!$this->compareUris($redirectUri, $clientRedirectUri)) {
                throw new InvalidRequestException('Redirect URI does not match.');
            }
        } else {
            // use registered redirect uri or throw exception

            if (!$clientRedirectUri) {
                throw new InvalidRequestException('Redirect URI was not supplied or registered.');
            }

            $redirectUri = $clientRedirectUri;
        }

        $requestedScopes = $request->query('scope');
        $availableScopes = $user->getScopes();

        if (!$availableScopes) {
            $availableScopes = $this->scopeResolver->getDefaultScopes();
        }

        if (empty($availableScopes)) {
            throw new InvalidScopeException('Scope parameter has to be specified.');
        }

        $scopes = $this->scopeResolver->intersect($requestedScopes, $availableScopes);

        return [
            'client' => $client,
            'redirect_uri' => $redirectUri,
            'state' => $request->query('state'),
            'scopes' => $scopes
        ];
    }