Merge pull request #10588 from nextcloud/fix/single-2fa-provider-login-redirect

Fix login redirection if only one 2FA provider is active
This commit is contained in:
Roeland Jago Douma 2018-08-09 12:27:29 +02:00 committed by GitHub
commit 0757c52980
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 6 deletions

View File

@ -334,7 +334,7 @@ class LoginController extends Controller {
if ($this->twoFactorManager->isTwoFactorAuthenticated($loginResult)) { if ($this->twoFactorManager->isTwoFactorAuthenticated($loginResult)) {
$this->twoFactorManager->prepareTwoFactorLogin($loginResult, $remember_login); $this->twoFactorManager->prepareTwoFactorLogin($loginResult, $remember_login);
$providers = $this->twoFactorManager->getProviderSet($loginResult)->getProviders(); $providers = $this->twoFactorManager->getProviderSet($loginResult)->getPrimaryProviders();
if (count($providers) === 1) { if (count($providers) === 1) {
// Single provider, hence we can redirect to that provider's challenge page directly // Single provider, hence we can redirect to that provider's challenge page directly
/* @var $provider IProvider */ /* @var $provider IProvider */

View File

@ -25,6 +25,8 @@ declare(strict_types=1);
namespace OC\Authentication\TwoFactorAuth; namespace OC\Authentication\TwoFactorAuth;
use function array_filter;
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\Authentication\TwoFactorAuth\IProvider; use OCP\Authentication\TwoFactorAuth\IProvider;
/** /**
@ -65,6 +67,15 @@ class ProviderSet {
return $this->providers; return $this->providers;
} }
/**
* @return IProvider[]
*/
public function getPrimaryProviders(): array {
return array_filter($this->providers, function(IProvider $provider) {
return !($provider instanceof BackupCodesProvider);
});
}
public function isProviderMissing(): bool { public function isProviderMissing(): bool {
return $this->providerMissing; return $this->providerMissing;
} }

View File

@ -27,6 +27,7 @@ use OC\Authentication\TwoFactorAuth\ProviderSet;
use OC\Core\Controller\LoginController; use OC\Core\Controller\LoginController;
use OC\Security\Bruteforce\Throttler; use OC\Security\Bruteforce\Throttler;
use OC\User\Session; use OC\User\Session;
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\Authentication\TwoFactorAuth\IProvider; use OCP\Authentication\TwoFactorAuth\IProvider;
@ -594,7 +595,10 @@ class LoginControllerTest extends TestCase {
->will($this->returnValue('john')); ->will($this->returnValue('john'));
$password = 'secret'; $password = 'secret';
$challengeUrl = 'challenge/url'; $challengeUrl = 'challenge/url';
$provider = $this->createMock(IProvider::class); $provider1 = $this->createMock(IProvider::class);
$provider1->method('getId')->willReturn('u2f');
$provider2 = $this->createMock(BackupCodesProvider::class);
$provider2->method('getId')->willReturn('backup');
$this->request $this->request
->expects($this->once()) ->expects($this->once())
@ -616,14 +620,11 @@ class LoginControllerTest extends TestCase {
$this->twoFactorManager->expects($this->once()) $this->twoFactorManager->expects($this->once())
->method('prepareTwoFactorLogin') ->method('prepareTwoFactorLogin')
->with($user); ->with($user);
$providerSet = new ProviderSet([$provider], false); $providerSet = new ProviderSet([$provider1, $provider2], false);
$this->twoFactorManager->expects($this->once()) $this->twoFactorManager->expects($this->once())
->method('getProviderSet') ->method('getProviderSet')
->with($user) ->with($user)
->willReturn($providerSet); ->willReturn($providerSet);
$provider->expects($this->once())
->method('getId')
->will($this->returnValue('u2f'));
$this->urlGenerator->expects($this->once()) $this->urlGenerator->expects($this->once())
->method('linkToRoute') ->method('linkToRoute')
->with('core.TwoFactorChallenge.showChallenge', [ ->with('core.TwoFactorChallenge.showChallenge', [

View File

@ -26,6 +26,7 @@ declare(strict_types=1);
namespace Test\Authentication\TwoFactorAuth; namespace Test\Authentication\TwoFactorAuth;
use OC\Authentication\TwoFactorAuth\ProviderSet; use OC\Authentication\TwoFactorAuth\ProviderSet;
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\Authentication\TwoFactorAuth\IProvider; use OCP\Authentication\TwoFactorAuth\IProvider;
use Test\TestCase; use Test\TestCase;
@ -49,6 +50,23 @@ class ProviderSetTest extends TestCase {
$this->assertEquals($expected, $set->getProviders()); $this->assertEquals($expected, $set->getProviders());
} }
public function testGet3rdPartyProviders() {
$p1 = $this->createMock(IProvider::class);
$p1->method('getId')->willReturn('p1');
$p2 = $this->createMock(IProvider::class);
$p2->method('getId')->willReturn('p2');
$p3 = $this->createMock(BackupCodesProvider::class);
$p3->method('getId')->willReturn('p3');
$expected = [
'p1' => $p1,
'p2' => $p2,
];
$set = new ProviderSet([$p2, $p1], false);
$this->assertEquals($expected, $set->getPrimaryProviders());
}
public function testGetProvider() { public function testGetProvider() {
$p1 = $this->createMock(IProvider::class); $p1 = $this->createMock(IProvider::class);
$p1->method('getId')->willReturn('p1'); $p1->method('getId')->willReturn('p1');