You are here

private function OpenIDConnect::buildContext in OpenID Connect / OAuth client 2.x

Same name and namespace in other branches
  1. 8 src/OpenIDConnect.php \Drupal\openid_connect\OpenIDConnect::buildContext()

Fill the context array.

Parameters

\Drupal\openid_connect\OpenIDConnectClientEntityInterface $client: The client.

array $tokens: The tokens as returned by OpenIDConnectClientInterface::retrieveTokens().

Return value

array|bool Context array or FALSE if an error was raised.

2 calls to OpenIDConnect::buildContext()
OpenIDConnect::completeAuthorization in src/OpenIDConnect.php
Complete the authorization after tokens have been retrieved.
OpenIDConnect::connectCurrentUser in src/OpenIDConnect.php
Connect the current user's account to an external provider.

File

src/OpenIDConnect.php, line 230

Class

OpenIDConnect
Main service of the OpenID Connect module.

Namespace

Drupal\openid_connect

Code

private function buildContext(OpenIDConnectClientEntityInterface $client, array $tokens) {
  $plugin = $client
    ->getPlugin();
  $user_data = isset($tokens['id_token']) ? is_string($tokens['id_token']) ? $this
    ->parseToken($tokens['id_token']) : $tokens['id_token'] : NULL;
  $access_data = isset($tokens['access_token']) ? is_string($tokens['access_token']) ? $this
    ->parseToken($tokens['access_token']) : $tokens['access_token'] : NULL;
  if ($plugin
    ->usesUserInfo()) {
    $userinfo = $plugin
      ->retrieveUserInfo($tokens['access_token']);
  }
  elseif (is_array($user_data)) {
    $userinfo = $user_data;
  }
  elseif (is_array($access_data)) {
    $userinfo = $access_data;
  }
  else {
    $userinfo = [];
  }
  $provider = $client
    ->id();
  $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) || !is_array($user_data)) && empty($userinfo)) {
    $this->logger
      ->error('No user information provided by @provider', [
      '@provider' => $provider,
    ]);
    return FALSE;
  }
  if ($userinfo && empty($userinfo['email'])) {
    $this->logger
      ->error('No e-mail address provided by @provider', [
      '@provider' => $provider,
    ]);
    return FALSE;
  }
  if (isset($user_data) && isset($user_data['sub'])) {

    // Set sub to FALSE, when it exists in both $user_data and $userinfo,
    // and they differ.
    $sub = !isset($userinfo['sub']) || $user_data['sub'] == $userinfo['sub'] ? $user_data['sub'] : FALSE;
  }
  else {

    // No sub in $user_data, set it from $userinfo if it exists.
    $sub = isset($userinfo['sub']) ? $userinfo['sub'] : FALSE;
  }
  if (empty($sub)) {
    $this->logger
      ->error('No "sub" found from @provider', [
      '@provider' => $provider,
    ]);
    return FALSE;
  }

  /** @var \Drupal\user\UserInterface|bool $account */
  $account = $this->externalAuth
    ->load($sub, 'openid_connect.' . $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,
  ]);
  if (is_array($results)) {

    // 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;
}