You are here

public function OpenIDConnectTest::testCompleteAuthorization in OpenID Connect / OAuth client 2.x

Same name and namespace in other branches
  1. 8 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|string $userData: The user data.

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 486

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, $userData, array $userInfo, bool $preAuthorize, bool $accountExists) : void {
  $clientId = $this
    ->randomMachineName();
  $this->currentUser
    ->expects($this
    ->once())
    ->method('isAuthenticated')
    ->willReturn($authenticated);
  $client = $this
    ->createMock(OpenIDConnectClientInterface::class);
  $clientEntity = $this
    ->createMock(OpenIDConnectClientEntityInterface::class);
  if ($authenticated) {
    $this
      ->expectException('RuntimeException');
  }
  else {
    $client
      ->expects($this
      ->once())
      ->method('usesUserInfo')
      ->willReturn(TRUE);
    $client
      ->expects($this
      ->once())
      ->method('retrieveUserInfo')
      ->with($tokens['access_token'])
      ->willReturn($userInfo);
    $clientEntity
      ->expects($this
      ->any())
      ->method('getPlugin')
      ->willReturn($client);
    $clientEntity
      ->expects($this
      ->any())
      ->method('id')
      ->willReturn($clientId);
    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' => $clientId,
        'user_data' => $userData,
      ]);
      if (empty($userData) && empty($userInfo)) {
        $this->oidcLogger
          ->expects($this
          ->once())
          ->method('error')
          ->with('No user information provided by @provider', [
          '@provider' => $clientId,
        ]);
      }
      if (!empty($userInfo) && empty($userInfo['email'])) {
        $this->oidcLogger
          ->expects($this
          ->once())
          ->method('error')
          ->with('No e-mail address provided by @provider', [
          '@provider' => $clientId,
        ]);
      }
      if (!empty($userInfo['sub'])) {
        $account = $this
          ->createMock(UserInterface::class);
        $account
          ->method('id')
          ->willReturn(1234);
        $account
          ->method('isNew')
          ->willReturn(FALSE);
        $this->externalAuth
          ->expects($this
          ->once())
          ->method('load')
          ->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->externalAuth
        ->expects($this
        ->once())
        ->method('load')
        ->willReturn($account);
      $this->moduleHandler
        ->expects($this
        ->any())
        ->method('invokeAll')
        ->with('openid_connect_pre_authorize')
        ->willReturn([]);
      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' => $clientId,
            '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 (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);
          $ret = !(empty($userInfo['registerOverride']) && isset($userInfo['newAccount']) && $userInfo['newAccount']);

          // @todo This can't probably use Consecutive.
          $immutableConfig
            ->expects($this
            ->any())
            ->method('get')
            ->withConsecutive([
            'connect_existing_users',
          ], [
            'override_registration_settings',
          ], [
            'userinfo_mappings',
          ])
            ->willReturn($ret, $ret, [
            'mail' => 'mail',
          ]);
          $this->configFactory
            ->expects($this
            ->any())
            ->method('get')
            ->with('openid_connect.settings')
            ->willReturn($immutableConfig);
          $userImmutableConfig = $this
            ->createMock(ImmutableConfig::class);
          $userImmutableConfig
            ->expects($this
            ->any())
            ->method('get')
            ->with('register')
            ->willReturn($userInfo['register'] ?? FALSE);
          $this->configFactory
            ->expects($this
            ->any())
            ->method('get')
            ->with('user.settings')
            ->willReturn($userImmutableConfig);
        }
      }
    }
  }
  $oidcMock = $this
    ->getMockBuilder('\\Drupal\\openid_connect\\OpenIDConnect')
    ->setConstructorArgs([
    $this->configFactory,
    $this->authmap,
    $this->externalAuth,
    $this->entityTypeManager,
    $this->entityFieldManager,
    $this->currentUser,
    $this->userData,
    $this->emailValidator,
    $this->messenger,
    $this->moduleHandler,
    $this->logger,
    $this->fileSystem,
    $this->session,
  ])
    ->setMethods([
    'userPropertiesIgnore',
    'createUser',
  ])
    ->getMock();
  $oidcMock
    ->method('userPropertiesIgnore')
    ->willReturn([
    'uid' => 'uid',
    'name' => 'name',
  ]);
  $oidcMock
    ->method('createUser')
    ->willReturn($this
    ->createMock(UserInterface::class));
  $authorization = $oidcMock
    ->completeAuthorization($clientEntity, $tokens);
  if (empty($userData) && empty($userInfo)) {
    $this
      ->assertEquals(FALSE, $authorization);
  }
  if (!empty($userInfo) && empty($userInfo['email'])) {
    $this
      ->assertEquals(FALSE, $authorization);
  }
}