Trying to access array offset on value of type bool in Drupal\openid_connect\Form\OpenIDConnectSettingsForm->buildForm()

Created on 1 July 2024, 3 days ago

Problem/Motivation

This error message appears when there is an exception when user information is retrieved with access token and $userinfo is set to FALSE.

Trying to access array offset on value of type bool in Drupal\openid_connect\Form\OpenIDConnectSettingsForm->buildForm() (line 273 of modules/contrib/openid_connect/src/Form/OpenIDConnectSettingsForm.php).

Steps to reproduce

Variable $userinfo is FALSE.
Variable $user_data is not empty.
Variable $results is FALSE.

private function buildContext(OpenIDConnectClientInterface $client, array $tokens) {
    $user_data = $client->decodeIdToken($tokens['id_token']);
    $userinfo = $client->retrieveUserInfo($tokens['access_token']);
    $provider = $client->getPluginId();

    $context = [
      'tokens' => $tokens,
      'plugin_id' => $provider,
      'user_data' => $user_data,
    ];
    $this->moduleHandler->alter('openid_connect_userinfo', $userinfo, $context);

    // Whether we have no usable user information.
    if (empty($user_data) && empty($userinfo)) {
      $this->logger->error('No user information provided by @provider (@code @error). Details: @details', ['@provider' => $provider]);
      return FALSE;
    }

    if ($userinfo && empty($userinfo['email'])) {
      $this->logger->error('No e-mail address provided by @provider (@code @error). Details: @details', ['@provider' => $provider]);
      return FALSE;
    }

    $sub = $this->extractSub($user_data, $userinfo);
    if (empty($sub)) {
      $this->logger->error('No "sub" found from @provider (@code @error). Details: @details', ['@provider' => $provider]);
      return FALSE;
    }

    /** @var \Drupal\user\UserInterface|bool $account */
    $account = $this->authmap->userLoadBySub($sub, $provider);
    $context = [
      'tokens' => $tokens,
      'plugin_id' => $provider,
      'user_data' => $user_data,
      'userinfo' => $userinfo,
      'sub' => $sub,
      'account' => $account,
    ];
    $results = $this->moduleHandler->invokeAll('openid_connect_pre_authorize', [
      $account,
      $context,
    ]);

    // Deny access if any module returns FALSE.
    if (in_array(FALSE, $results, TRUE)) {
      $this->logger->error('Login denied for @email via pre-authorize hook.', ['@email' => $userinfo['email']]);
      return FALSE;
    }

    // If any module returns an account, set local $account to that.
    foreach ($results as $result) {
      if ($result instanceof UserInterface) {
        $context['account'] = $result;
        break;
      }
    }

    return $context;
  }

Code will try to log an error with $userinfo['email'] but $userinfo is FALSE so we will get a warning.

Proposed resolution

Change this part of code:

if ($userinfo && empty($userinfo['email'])) {
      $this->logger->error('No e-mail address provided by @provider (@code @error). Details: @details', ['@provider' => $provider]);
      return FALSE;
    }

By this one:

if (!$userinfo || empty($userinfo['email'])) {
      $this->logger->error('No e-mail address provided by @provider (@code @error). Details: @details', ['@provider' => $provider]);
      return FALSE;
    }

This way, when $userinfo is FALSE, the error message "No e-mail address provided..." will be displayed instead of continuing code execution.

Remaining tasks

User interface changes

API changes

Data model changes

πŸ› Bug report
Status

Postponed: needs info

Version

1.4

Component

Code

Created by

πŸ‡ͺπŸ‡ΈSpain kikecastillo Barcelona

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @kikecastillo
  • πŸ‡ͺπŸ‡ΈSpain kikecastillo Barcelona

    kikecastillo β†’ changed the visibility of the branch 3458320-trying-to-access to hidden.

  • Status changed to Postponed: needs info 3 days ago
  • πŸ‡΅πŸ‡ΉPortugal jcnventura

    PHP uses short-circuit operators in && operators. The only way to get to the second operator is if the first one is evaluated to true. In this case, since the error is complaining about it being a boolean, it means that $userinfo is TRUE.

    It is hard to understand what the origin of the problem is here, since the error is in line 273 of OpenIDConnectSettingsForm, specifically in the buildForm() method, but that method is defined in lines 123 to 272 (see https://git.drupalcode.org/project/openid_connect/-/blob/8.x-1.4/src/For...)

    Can you please confirm the version of the module that you're running, and what patches you're applying to it?

Production build 0.69.0 2024