You are here

public function OpenIDConnectTest::testCompleteAuthorization in OpenID Connect / OAuth client 8

Same name and namespace in other branches
  1. 2.x tests/src/Unit/OpenIDConnectTest.php \Drupal\Tests\openid_connect\Unit\OpenIDConnectTest::testCompleteAuthorization()

Test coverate for the completeAuthorization() method.

@dataProvider dataProviderForCompleteAuthorization @runInSeparateProcess

Parameters

bool $authenticated: Should the user be authenticated.

string $destination: Destination string.

array $tokens: Tokens array.

array $userData: The user data array.

array $userInfo: The user info array.

bool $preAuthorize: Whether to preauthorize or not.

bool $accountExists: Does the account already exist.

File

tests/src/Unit/OpenIDConnectTest.php, line 559

Class

OpenIDConnectTest
Provides tests for the OpenID Connect module.

Namespace

Drupal\Tests\openid_connect\Unit

Code

public function testCompleteAuthorization(bool $authenticated, string $destination, array $tokens, array $userData, array $userInfo, bool $preAuthorize, bool $accountExists) : void {
  $clientPluginId = $this
    ->randomMachineName();
  $this->currentUser
    ->expects($this
    ->once())
    ->method('isAuthenticated')
    ->willReturn($authenticated);
  $client = $this
    ->createMock(OpenIDConnectClientInterface::class);
  if ($authenticated) {
    $this
      ->expectException('RuntimeException');
  }
  else {
    $client
      ->expects($this
      ->once())
      ->method('decodeIdToken')
      ->with($tokens['id_token'])
      ->willReturn($userData);
    $client
      ->expects($this
      ->once())
      ->method('retrieveUserInfo')
      ->with($tokens['access_token'])
      ->willReturn($userInfo);
    $client
      ->expects($this
      ->any())
      ->method('getPluginId')
      ->willReturn($clientPluginId);
    if ($accountExists) {
      if (!$preAuthorize) {
        $moduleHandlerResults = [
          1,
          2,
          FALSE,
        ];
      }
      else {
        $returnedAccount = $this
          ->createMock(UserInterface::class);
        if (!empty($userInfo['blocked'])) {
          $returnedAccount
            ->expects($this
            ->once())
            ->method('isBlocked')
            ->willReturn(TRUE);
          $this->messenger
            ->expects($this
            ->once())
            ->method('addError');
        }
        $moduleHandlerResults = [
          $returnedAccount,
        ];
      }
      $this->moduleHandler
        ->expects($this
        ->once())
        ->method('alter')
        ->with('openid_connect_userinfo', $userInfo, [
        'tokens' => $tokens,
        'plugin_id' => $clientPluginId,
        'user_data' => $userData,
      ]);
      if (empty($userData) && empty($userInfo)) {
        $this->oidcLogger
          ->expects($this
          ->once())
          ->method('error')
          ->with('No user information provided by @provider (@code @error). Details: @details', [
          '@provider' => $clientPluginId,
        ]);
      }
      if (!empty($userInfo) && empty($userInfo['email'])) {
        $this->oidcLogger
          ->expects($this
          ->once())
          ->method('error')
          ->with('No e-mail address provided by @provider (@code @error). Details: @details', [
          '@provider' => $clientPluginId,
        ]);
      }
      if (!empty($userInfo['sub'])) {
        $account = $this
          ->createMock(UserInterface::class);
        $account
          ->method('id')
          ->willReturn(1234);
        $account
          ->method('isNew')
          ->willReturn(FALSE);
        $this->authMap
          ->expects($this
          ->once())
          ->method('userLoadBySub')
          ->willReturn($account);
        $this->moduleHandler
          ->expects($this
          ->any())
          ->method('invokeAll')
          ->withConsecutive([
          'openid_connect_pre_authorize',
        ], [
          'openid_connect_userinfo_save',
        ], [
          'openid_connect_post_authorize',
        ])
          ->willReturnOnConsecutiveCalls($moduleHandlerResults, TRUE, TRUE);
        if ($preAuthorize) {
          $this->entityFieldManager
            ->expects($this
            ->once())
            ->method('getFieldDefinitions')
            ->with('user', 'user')
            ->willReturn([
            'mail' => 'mail',
          ]);
          $immutableConfig = $this
            ->createMock(ImmutableConfig::class);
          $immutableConfig
            ->expects($this
            ->exactly(2))
            ->method('get')
            ->withConsecutive([
            'always_save_userinfo',
          ], [
            'userinfo_mappings',
          ])
            ->willReturnOnConsecutiveCalls(TRUE, [
            'mail',
            'name',
          ]);
          $this->configFactory
            ->expects($this
            ->exactly(2))
            ->method('get')
            ->with('openid_connect.settings')
            ->willReturn($immutableConfig);
        }
      }
    }
    else {
      $account = FALSE;
      $this->authMap
        ->expects($this
        ->once())
        ->method('userLoadBySub')
        ->willReturn($account);
      $this->moduleHandler
        ->expects($this
        ->any())
        ->method('invokeAll')
        ->willReturnCallback(function (...$args) {
        $return = NULL;
        switch ($args[0]) {
          case 'openid_connect_pre_authorize':
            $return = [];
            break;
          default:
            $return = NULL;
            break;
        }
        return $return;
      });
      if ($userInfo['email'] === 'invalid') {
        $this->messenger
          ->expects($this
          ->once())
          ->method('addError');
      }
      else {
        if ($userInfo['email'] === 'duplicate@valid.com') {
          $account = $this
            ->createMock(UserInterface::class);
          $this->userStorage
            ->expects($this
            ->once())
            ->method('loadByProperties')
            ->with([
            'mail' => $userInfo['email'],
          ])
            ->willReturn([
            $account,
          ]);
          $immutableConfig = $this
            ->createMock(ImmutableConfig::class);
          $immutableConfig
            ->expects($this
            ->once())
            ->method('get')
            ->with('connect_existing_users')
            ->willReturn(FALSE);
          $this->configFactory
            ->expects($this
            ->once())
            ->method('get')
            ->with('openid_connect.settings')
            ->willReturn($immutableConfig);
          $this->messenger
            ->expects($this
            ->once())
            ->method('addError');
        }
        elseif ($userInfo['email'] === 'connect@valid.com') {
          $this->entityFieldManager
            ->expects($this
            ->any())
            ->method('getFieldDefinitions')
            ->with('user', 'user')
            ->willReturn([
            'mail' => 'mail',
          ]);
          $context = [
            'tokens' => $tokens,
            'plugin_id' => $clientPluginId,
            'user_data' => $userData,
          ];
          $this->moduleHandler
            ->expects($this
            ->once())
            ->method('alter')
            ->with('openid_connect_userinfo', $userInfo, $context);
          if (isset($userInfo['newAccount']) && $userInfo['newAccount']) {
            $account = FALSE;
          }
          else {
            $account = $this
              ->createMock(UserInterface::class);
            if (isset($userInfo['blocked']) && $userInfo['blocked']) {
              $account
                ->expects($this
                ->once())
                ->method('isBlocked')
                ->willReturn(TRUE);
              if ($accountExists) {
                $this->messenger
                  ->expects($this
                  ->once())
                  ->method('addError');
              }
            }
          }
          if (isset($userInfo['newAccount']) && $userInfo['newAccount']) {
            $this->userStorage
              ->expects($this
              ->once())
              ->method('loadByProperties')
              ->with([
              'mail' => $userInfo['email'],
            ])
              ->willReturn(FALSE);
          }
          else {
            $this->userStorage
              ->expects($this
              ->once())
              ->method('loadByProperties')
              ->with([
              'mail' => $userInfo['email'],
            ])
              ->willReturn([
              $account,
            ]);
          }
          if (isset($userInfo['register'])) {
            switch ($userInfo['register']) {
              case 'admin_only':
                if (empty($userInfo['registerOverride'])) {
                  $this->messenger
                    ->expects($this
                    ->once())
                    ->method('addError');
                }
                break;
              case 'visitors_admin_approval':
                $this->messenger
                  ->expects($this
                  ->once())
                  ->method('addMessage');
                break;
            }
          }
          $immutableConfig = $this
            ->createMock(ImmutableConfig::class);
          $immutableConfig
            ->expects($this
            ->any())
            ->method('get')
            ->willReturnCallback(function ($config) use ($userInfo) {
            $return = FALSE;
            switch ($config) {
              case 'connect_existing_users':
              case 'override_registration_settings':
                if (empty($userInfo['registerOverride']) && isset($userInfo['newAccount']) && $userInfo['newAccount']) {
                  $return = FALSE;
                }
                else {
                  $return = TRUE;
                }
                break;
              case 'register':
                if (isset($userInfo['register'])) {
                  $return = $userInfo['register'];
                }
                break;
              case 'userinfo_mappings':
                $return = [
                  'mail' => 'mail',
                ];
                break;
            }
            return $return;
          });
          $this->configFactory
            ->expects($this
            ->any())
            ->method('get')
            ->willReturnCallback(function ($config) use ($immutableConfig) {
            if ($config === 'openid_connect.settings' || $config === 'user.settings') {
              return $immutableConfig;
            }
            return FALSE;
          });
        }
      }
    }
  }
  $oidcMock = $this
    ->getMockBuilder('\\Drupal\\openid_connect\\OpenIDConnect')
    ->setConstructorArgs([
    $this->configFactory,
    $this->authMap,
    $this->entityTypeManager,
    $this->entityFieldManager,
    $this->currentUser,
    $this->userData,
    $this->emailValidator,
    $this->messenger,
    $this->moduleHandler,
    $this->logger,
    $this->fileSystem,
  ])
    ->setMethods([
    'userPropertiesIgnore',
    'createUser',
  ])
    ->getMock();
  $oidcMock
    ->method('userPropertiesIgnore')
    ->willReturn([
    'uid' => 'uid',
    'name' => 'name',
  ]);
  $oidcMock
    ->method('createUser')
    ->willReturn($this
    ->createMock(UserInterface::class));
  $authorization = $oidcMock
    ->completeAuthorization($client, $tokens, $destination);
  if (empty($userData) && empty($userInfo)) {
    $this
      ->assertEquals(FALSE, $authorization);
  }
  if (!empty($userInfo) && empty($userInfo['email'])) {
    $this
      ->assertEquals(FALSE, $authorization);
  }
}