public function authorize(ServerRequestInterface $request, ResponseInterface $response, $url = '/', $destination = null, $options = [])
    {
        // Make sure we're making request with the authorization_code grant.
        $this->asUser();

        $url = $this->getFrameworkBridge()->prepareUrl($url);
        $query = $request->getQueryParams();

        // If we don't have an authorization code then make one and redirect.
        if (! isset($query['code'])) {
            $params = array_merge($options, [
                'scope' => $this->config['authorization_code']['scope'],
                'destination' => ! empty($destination) ? $destination : null,
            ]);
            $authorizationUrl = $this->getAuthorizationServer()->getAuthorizationUrl($params);

            // Get the state generated for you and store it to the session.
            $state = $this->getAuthorizationServer()->getState();
            $this->getFrameworkBridge()->saveStateToken($state);

            // Redirect the user to the authorization URL.
            return $response->withStatus(302)->withHeader('Location', $authorizationUrl);
        }

        // Check given state against previously stored one to mitigate CSRF attack
        if (! (isset($query['state']) && $query['state'] === $this->getFrameworkBridge()->getStateToken())) {
            throw new InternalException('[authorization_code]', 500, 'The OAuth state field did not match.');
        }

        $token = $this->getTokenByAuthorizationCodeGrant($query['code']);
        if (! $token) {
            throw new InternalException('[authorization_code]', 500, 'The authorization server did not return a valid access token.');
        }

        // Find or create a local user account, and create a session for them.
        $user = $this->getFrameworkBridge()->getOrCreateUser($token->getResourceOwnerId());
        $this->getFrameworkBridge()->login($user, $token);

        return $response->withStatus(302)->withHeader('Location', $url);
    }