Skip to content

Commit

Permalink
Merge pull request #10578 from nextcloud/fix/2fa-provider-registry-po…
Browse files Browse the repository at this point in the history
…pulation

Fix 2FA provider registry population on login
  • Loading branch information
rullzer authored Aug 8, 2018
2 parents e595cad + d248a0b commit a3fdec7
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 4 deletions.
4 changes: 3 additions & 1 deletion lib/private/Authentication/TwoFactorAuth/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ public function isTwoFactorAuthenticated(IUser $user): bool {
}

$providerStates = $this->providerRegistry->getProviderStates($user);
$enabled = array_filter($providerStates);
$providers = $this->providerLoader->getProviders($user);
$fixedStates = $this->fixMissingProviderStates($providerStates, $providers, $user);
$enabled = array_filter($fixedStates);

return $twoFactorEnabled && !empty($enabled);
}
Expand Down
82 changes: 79 additions & 3 deletions tests/lib/Authentication/TwoFactorAuth/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ protected function setUp() {

$this->fakeProvider = $this->createMock(IProvider::class);
$this->fakeProvider->method('getId')->willReturn('email');
$this->fakeProvider->method('isTwoFactorAuthEnabledForUser')->willReturn(true);

$this->backupProvider = $this->getMockBuilder('\OCP\Authentication\TwoFactorAuth\IProvider')->getMock();
$this->backupProvider->method('getId')->willReturn('backup_codes');
Expand Down Expand Up @@ -143,7 +142,25 @@ private function prepareProvidersWitBackupProvider() {
]);
}

public function testIsTwoFactorAuthenticated() {
public function testIsTwoFactorAuthenticatedNoProviders() {
$this->user->expects($this->once())
->method('getUID')
->will($this->returnValue('user123'));
$this->config->expects($this->once())
->method('getUserValue')
->with('user123', 'core', 'two_factor_auth_disabled', 0)
->willReturn(0);
$this->providerRegistry->expects($this->once())
->method('getProviderStates')
->willReturn([]); // No providers registered
$this->providerLoader->expects($this->once())
->method('getProviders')
->willReturn([]); // No providers loadable

$this->assertFalse($this->manager->isTwoFactorAuthenticated($this->user));
}

public function testIsTwoFactorAuthenticatedFailingProviders() {
$this->user->expects($this->once())
->method('getUID')
->will($this->returnValue('user123'));
Expand All @@ -156,11 +173,70 @@ public function testIsTwoFactorAuthenticated() {
->willReturn([
'twofactor_totp' => true,
'twofactor_u2f' => false,
]);
]); // Two providers registered, but …
$this->providerLoader->expects($this->once())
->method('getProviders')
->willReturn([]); // … none of them is able to load, however …

// … 2FA is still enforced
$this->assertTrue($this->manager->isTwoFactorAuthenticated($this->user));
}

public function providerStatesFixData(): array {
return [
[false, false],
[true, true],
];
}

/**
* If the 2FA registry has not been populated when a user logs in,
* the 2FA manager has to first fix the state before it checks for
* enabled providers.
*
* If any of these providers is active, 2FA is enabled
*
* @dataProvider providerStatesFixData
*/
public function testIsTwoFactorAuthenticatedFixesProviderStates(bool $providerEnabled, bool $expected) {
$this->user->expects($this->once())
->method('getUID')
->will($this->returnValue('user123'));
$this->config->expects($this->once())
->method('getUserValue')
->with('user123', 'core', 'two_factor_auth_disabled', 0)
->willReturn(0);
$this->providerRegistry->expects($this->once())
->method('getProviderStates')
->willReturn([]); // Nothing registered yet
$this->providerLoader->expects($this->once())
->method('getProviders')
->willReturn([
$this->fakeProvider
]);
$this->fakeProvider->expects($this->once())
->method('isTwoFactorAuthEnabledForUser')
->with($this->user)
->willReturn($providerEnabled);
if ($providerEnabled) {
$this->providerRegistry->expects($this->once())
->method('enableProviderFor')
->with(
$this->fakeProvider,
$this->user
);
} else {
$this->providerRegistry->expects($this->once())
->method('disableProviderFor')
->with(
$this->fakeProvider,
$this->user
);
}

$this->assertEquals($expected, $this->manager->isTwoFactorAuthenticated($this->user));
}

public function testGetProvider() {
$this->providerRegistry->expects($this->once())
->method('getProviderStates')
Expand Down

0 comments on commit a3fdec7

Please sign in to comment.