diff options
author | Morris Jobke <hey@morrisjobke.de> | 2016-11-02 18:32:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-02 18:32:38 +0100 |
commit | e6b52ef4cd1a92004895320d52f08b44a8b422d3 (patch) | |
tree | f83153d562040f0a2c4f4b34abb42acbd1edc0a8 /tests | |
parent | e81d04cd8d2ac0de3d06d4586550469384c5d91a (diff) | |
parent | 4da6b20e768574e2ec6a7da590273e18b64ddda5 (diff) | |
download | nextcloud-server-e6b52ef4cd1a92004895320d52f08b44a8b422d3.tar.gz nextcloud-server-e6b52ef4cd1a92004895320d52f08b44a8b422d3.zip |
Merge pull request #1347 from nextcloud/bring-back-remember-me
fix remember me login
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Core/Controller/LoginControllerTest.php | 72 | ||||
-rw-r--r-- | tests/lib/Authentication/Token/DefaultTokenMapperTest.php | 1 | ||||
-rw-r--r-- | tests/lib/Authentication/Token/DefaultTokenProviderTest.php | 136 | ||||
-rw-r--r-- | tests/lib/Authentication/TwoFactorAuth/ManagerTest.php | 29 | ||||
-rw-r--r-- | tests/lib/User/SessionTest.php | 407 |
5 files changed, 471 insertions, 174 deletions
diff --git a/tests/Core/Controller/LoginControllerTest.php b/tests/Core/Controller/LoginControllerTest.php index ff50ac98fbd..d16b9b114f3 100644 --- a/tests/Core/Controller/LoginControllerTest.php +++ b/tests/Core/Controller/LoginControllerTest.php @@ -322,6 +322,8 @@ class LoginControllerTest extends TestCase { $this->userSession->expects($this->never()) ->method('createSessionToken'); + $this->userSession->expects($this->never()) + ->method('createRememberMeToken'); $this->config->expects($this->never()) ->method('deleteUserValue'); @@ -363,7 +365,7 @@ class LoginControllerTest extends TestCase { ->with($user, $password); $this->userSession->expects($this->once()) ->method('createSessionToken') - ->with($this->request, $user->getUID(), $user, $password); + ->with($this->request, $user->getUID(), $user, $password, false); $this->twoFactorManager->expects($this->once()) ->method('isTwoFactorAuthenticated') ->with($user) @@ -371,11 +373,63 @@ class LoginControllerTest extends TestCase { $this->config->expects($this->once()) ->method('deleteUserValue') ->with('uid', 'core', 'lostpassword'); + $this->userSession->expects($this->never()) + ->method('createRememberMeToken'); $expected = new \OCP\AppFramework\Http\RedirectResponse($indexPageUrl); $this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null)); } + public function testLoginWithValidCredentialsAndRememberMe() { + /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->getMockBuilder('\OCP\IUser')->getMock(); + $user->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('uid')); + $password = 'secret'; + $indexPageUrl = \OC_Util::getDefaultPageUrl(); + + $this->request + ->expects($this->exactly(2)) + ->method('getRemoteAddress') + ->willReturn('192.168.0.1'); + $this->request + ->expects($this->once()) + ->method('passesCSRFCheck') + ->willReturn(true); + $this->throttler + ->expects($this->once()) + ->method('sleepDelay') + ->with('192.168.0.1'); + $this->throttler + ->expects($this->once()) + ->method('getDelay') + ->with('192.168.0.1') + ->willReturn(200); + $this->userManager->expects($this->once()) + ->method('checkPassword') + ->will($this->returnValue($user)); + $this->userSession->expects($this->once()) + ->method('login') + ->with($user, $password); + $this->userSession->expects($this->once()) + ->method('createSessionToken') + ->with($this->request, $user->getUID(), $user, $password, true); + $this->twoFactorManager->expects($this->once()) + ->method('isTwoFactorAuthenticated') + ->with($user) + ->will($this->returnValue(false)); + $this->config->expects($this->once()) + ->method('deleteUserValue') + ->with('uid', 'core', 'lostpassword'); + $this->userSession->expects($this->once()) + ->method('createRememberMeToken') + ->with($user); + + $expected = new \OCP\AppFramework\Http\RedirectResponse($indexPageUrl); + $this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null, true)); + } + public function testLoginWithoutPassedCsrfCheckAndNotLoggedIn() { /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */ $user = $this->getMockBuilder('\OCP\IUser')->getMock(); @@ -408,6 +462,8 @@ class LoginControllerTest extends TestCase { ->will($this->returnValue(false)); $this->config->expects($this->never()) ->method('deleteUserValue'); + $this->userSession->expects($this->never()) + ->method('createRememberMeToken'); $expected = new \OCP\AppFramework\Http\RedirectResponse(\OC_Util::getDefaultPageUrl()); $this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl)); @@ -450,6 +506,8 @@ class LoginControllerTest extends TestCase { ->will($this->returnValue($redirectUrl)); $this->config->expects($this->never()) ->method('deleteUserValue'); + $this->userSession->expects($this->never()) + ->method('createRememberMeToken'); $expected = new \OCP\AppFramework\Http\RedirectResponse($redirectUrl); $this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl)); @@ -488,7 +546,7 @@ class LoginControllerTest extends TestCase { ->will($this->returnValue($user)); $this->userSession->expects($this->once()) ->method('createSessionToken') - ->with($this->request, $user->getUID(), 'Jane', $password); + ->with($this->request, $user->getUID(), 'Jane', $password, false); $this->userSession->expects($this->once()) ->method('isLoggedIn') ->with() @@ -540,7 +598,7 @@ class LoginControllerTest extends TestCase { ->with('john@doe.com', $password); $this->userSession->expects($this->once()) ->method('createSessionToken') - ->with($this->request, $user->getUID(), 'john@doe.com', $password); + ->with($this->request, $user->getUID(), 'john@doe.com', $password, false); $this->twoFactorManager->expects($this->once()) ->method('isTwoFactorAuthenticated') ->with($user) @@ -564,6 +622,8 @@ class LoginControllerTest extends TestCase { $this->config->expects($this->once()) ->method('deleteUserValue') ->with('john', 'core', 'lostpassword'); + $this->userSession->expects($this->never()) + ->method('createRememberMeToken'); $expected = new RedirectResponse($challengeUrl); $this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', $password, null)); @@ -605,7 +665,7 @@ class LoginControllerTest extends TestCase { ->with('john@doe.com', $password); $this->userSession->expects($this->once()) ->method('createSessionToken') - ->with($this->request, $user->getUID(), 'john@doe.com', $password); + ->with($this->request, $user->getUID(), 'john@doe.com', $password, false); $this->twoFactorManager->expects($this->once()) ->method('isTwoFactorAuthenticated') ->with($user) @@ -628,6 +688,8 @@ class LoginControllerTest extends TestCase { $this->config->expects($this->once()) ->method('deleteUserValue') ->with('john', 'core', 'lostpassword'); + $this->userSession->expects($this->never()) + ->method('createRememberMeToken'); $expected = new RedirectResponse($challengeUrl); $this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', $password, null)); @@ -680,6 +742,8 @@ class LoginControllerTest extends TestCase { ->with('login', '192.168.0.1', ['user' => 'john@doe.com']); $this->config->expects($this->never()) ->method('deleteUserValue'); + $this->userSession->expects($this->never()) + ->method('createRememberMeToken'); $expected = new RedirectResponse(''); $this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', 'just wrong', null)); diff --git a/tests/lib/Authentication/Token/DefaultTokenMapperTest.php b/tests/lib/Authentication/Token/DefaultTokenMapperTest.php index d71d9468477..418a4d14f62 100644 --- a/tests/lib/Authentication/Token/DefaultTokenMapperTest.php +++ b/tests/lib/Authentication/Token/DefaultTokenMapperTest.php @@ -130,6 +130,7 @@ class DefaultTokenMapperTest extends TestCase { $token->setName('Firefox on Android'); $token->setToken('1504445f1524fc801035448a95681a9378ba2e83930c814546c56e5d6ebde221198792fd900c88ed5ead0555780dad1ebce3370d7e154941cd5de87eb419899b'); $token->setType(IToken::TEMPORARY_TOKEN); + $token->setRemember(IToken::DO_NOT_REMEMBER); $token->setLastActivity($this->time - 60 * 60 * 24 * 3); $token->setLastCheck($this->time - 10); diff --git a/tests/lib/Authentication/Token/DefaultTokenProviderTest.php b/tests/lib/Authentication/Token/DefaultTokenProviderTest.php index 7f90cf051f4..5e4d4f94366 100644 --- a/tests/lib/Authentication/Token/DefaultTokenProviderTest.php +++ b/tests/lib/Authentication/Token/DefaultTokenProviderTest.php @@ -1,8 +1,8 @@ <?php - /** * @author Christoph Wurst <christoph@owncloud.com> * + * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch> * @copyright Copyright (c) 2016, ownCloud, Inc. * @license AGPL-3.0 * @@ -25,7 +25,7 @@ namespace Test\Authentication\Token; use OC\Authentication\Token\DefaultToken; use OC\Authentication\Token\DefaultTokenProvider; use OC\Authentication\Token\IToken; -use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\Mapper; use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\ILogger; @@ -35,13 +35,19 @@ use Test\TestCase; class DefaultTokenProviderTest extends TestCase { - /** @var DefaultTokenProvider */ + /** @var DefaultTokenProvider|\PHPUnit_Framework_MockObject_MockObject */ private $tokenProvider; + /** @var Mapper|\PHPUnit_Framework_MockObject_MockObject */ private $mapper; + /** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */ private $crypto; + /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ private $config; + /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */ private $logger; + /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */ private $timeFactory; + /** @var int */ private $time; protected function setUp() { @@ -81,6 +87,7 @@ class DefaultTokenProviderTest extends TestCase { $toInsert->setName($name); $toInsert->setToken(hash('sha512', $token . '1f4h9s')); $toInsert->setType($type); + $toInsert->setRemember(IToken::DO_NOT_REMEMBER); $toInsert->setLastActivity($this->time); $this->config->expects($this->any()) @@ -95,7 +102,7 @@ class DefaultTokenProviderTest extends TestCase { ->method('insert') ->with($this->equalTo($toInsert)); - $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type); + $actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER); $this->assertEquals($toInsert, $actual); } @@ -245,15 +252,128 @@ class DefaultTokenProviderTest extends TestCase { public function testInvalidateOldTokens() { $defaultSessionLifetime = 60 * 60 * 24; - $this->config->expects($this->once()) + $defaultRememberMeLifetime = 60 * 60 * 24 * 15; + $this->config->expects($this->exactly(2)) ->method('getSystemValue') - ->with('session_lifetime', $defaultSessionLifetime) - ->will($this->returnValue(150)); - $this->mapper->expects($this->once()) + ->will($this->returnValueMap([ + ['session_lifetime', $defaultSessionLifetime, 150], + ['remember_login_cookie_lifetime', $defaultRememberMeLifetime, 300], + ])); + $this->mapper->expects($this->at(0)) ->method('invalidateOld') ->with($this->time - 150); + $this->mapper->expects($this->at(1)) + ->method('invalidateOld') + ->with($this->time - 300); $this->tokenProvider->invalidateOldTokens(); } + public function testRenewSessionTokenWithoutPassword() { + $token = $this->getMockBuilder(DefaultToken::class) + ->disableOriginalConstructor() + ->setMethods(['getUID', 'getLoginName', 'getPassword', 'getName']) + ->getMock(); + $token + ->expects($this->at(0)) + ->method('getUID') + ->willReturn('UserUid'); + $token + ->expects($this->at(1)) + ->method('getLoginName') + ->willReturn('UserLoginName'); + $token + ->expects($this->at(2)) + ->method('getPassword') + ->willReturn(null); + $token + ->expects($this->at(3)) + ->method('getName') + ->willReturn('MyTokenName'); + $this->config + ->expects($this->exactly(2)) + ->method('getSystemValue') + ->with('secret') + ->willReturn('MyInstanceSecret'); + $this->mapper + ->expects($this->at(0)) + ->method('getToken') + ->with(hash('sha512', 'oldId' . 'MyInstanceSecret')) + ->willReturn($token); + $newToken = new DefaultToken(); + $newToken->setUid('UserUid'); + $newToken->setLoginName('UserLoginName'); + $newToken->setName('MyTokenName'); + $newToken->setToken(hash('sha512', 'newId' . 'MyInstanceSecret')); + $newToken->setType(IToken::TEMPORARY_TOKEN); + $newToken->setLastActivity(1313131); + $this->mapper + ->expects($this->at(1)) + ->method('insert') + ->with($newToken); + + $this->tokenProvider->renewSessionToken('oldId', 'newId'); + } + + public function testRenewSessionTokenWithPassword() { + $token = $this->getMockBuilder(DefaultToken::class) + ->disableOriginalConstructor() + ->setMethods(['getUID', 'getLoginName', 'getPassword', 'getName']) + ->getMock(); + $token + ->expects($this->at(0)) + ->method('getUID') + ->willReturn('UserUid'); + $token + ->expects($this->at(1)) + ->method('getLoginName') + ->willReturn('UserLoginName'); + $token + ->expects($this->at(2)) + ->method('getPassword') + ->willReturn('EncryptedPassword'); + $token + ->expects($this->at(3)) + ->method('getPassword') + ->willReturn('EncryptedPassword'); + $token + ->expects($this->at(4)) + ->method('getName') + ->willReturn('MyTokenName'); + $this->crypto + ->expects($this->any(0)) + ->method('decrypt') + ->with('EncryptedPassword', 'oldIdMyInstanceSecret') + ->willReturn('ClearTextPassword'); + $this->crypto + ->expects($this->any(1)) + ->method('encrypt') + ->with('ClearTextPassword', 'newIdMyInstanceSecret') + ->willReturn('EncryptedPassword'); + $this->config + ->expects($this->exactly(4)) + ->method('getSystemValue') + ->with('secret') + ->willReturn('MyInstanceSecret'); + $this->mapper + ->expects($this->at(0)) + ->method('getToken') + ->with(hash('sha512', 'oldId' . 'MyInstanceSecret')) + ->willReturn($token); + $newToken = new DefaultToken(); + $newToken->setUid('UserUid'); + $newToken->setLoginName('UserLoginName'); + $newToken->setName('MyTokenName'); + $newToken->setToken(hash('sha512', 'newId' . 'MyInstanceSecret')); + $newToken->setType(IToken::TEMPORARY_TOKEN); + $newToken->setLastActivity(1313131); + $newToken->setPassword('EncryptedPassword'); + $this->mapper + ->expects($this->at(1)) + ->method('insert') + ->with($newToken); + + $this->tokenProvider->renewSessionToken('oldId', 'newId'); + } + } diff --git a/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php b/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php index 72b70d817d2..52f3ca28500 100644 --- a/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php +++ b/tests/lib/Authentication/TwoFactorAuth/ManagerTest.php @@ -233,8 +233,15 @@ class ManagerTest extends TestCase { ->with($this->user, $challenge) ->will($this->returnValue(true)); $this->session->expects($this->once()) + ->method('get') + ->with('two_factor_remember_login') + ->will($this->returnValue(false)); + $this->session->expects($this->at(1)) ->method('remove') ->with('two_factor_auth_uid'); + $this->session->expects($this->at(2)) + ->method('remove') + ->with('two_factor_remember_login'); $this->assertTrue($this->manager->verifyChallenge('email', $this->user, $challenge)); } @@ -304,11 +311,29 @@ class ManagerTest extends TestCase { ->method('getUID') ->will($this->returnValue('ferdinand')); - $this->session->expects($this->once()) + $this->session->expects($this->at(0)) + ->method('set') + ->with('two_factor_auth_uid', 'ferdinand'); + $this->session->expects($this->at(1)) + ->method('set') + ->with('two_factor_remember_login', true); + + $this->manager->prepareTwoFactorLogin($this->user, true); + } + + public function testPrepareTwoFactorLoginDontRemember() { + $this->user->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('ferdinand')); + + $this->session->expects($this->at(0)) ->method('set') ->with('two_factor_auth_uid', 'ferdinand'); + $this->session->expects($this->at(1)) + ->method('set') + ->with('two_factor_remember_login', false); - $this->manager->prepareTwoFactorLogin($this->user); + $this->manager->prepareTwoFactorLogin($this->user, false); } } diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php index 268d8e10e5a..ee9ed737cf5 100644 --- a/tests/lib/User/SessionTest.php +++ b/tests/lib/User/SessionTest.php @@ -1,5 +1,4 @@ <?php - /** * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> * This file is licensed under the Affero General Public License version 3 or @@ -39,8 +38,16 @@ class SessionTest extends \Test\TestCase { protected $tokenProvider; /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ private $config; - /** @var Throttler */ + /** @var Throttler|\PHPUnit_Framework_MockObject_MockObject */ private $throttler; + /** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */ + private $random; + /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ + private $manager; + /** @var ISession|\PHPUnit_Framework_MockObject_MockObject */ + private $session; + /** @var Session|\PHPUnit_Framework_MockObject_MockObject */ + private $userSession; protected function setUp() { parent::setUp(); @@ -52,6 +59,24 @@ class SessionTest extends \Test\TestCase { $this->tokenProvider = $this->createMock(IProvider::class); $this->config = $this->createMock(IConfig::class); $this->throttler = $this->createMock(Throttler::class); + $this->random = $this->createMock(ISecureRandom::class); + $this->manager = $this->createMock(IUserManager::class); + $this->session = $this->createMock(ISession::class); + $this->userSession = $this->getMockBuilder(Session::class) + ->setConstructorArgs([ + $this->manager, + $this->session, + $this->timeFactory, + $this->tokenProvider, + $this->config, + $this->random, + ]) + ->setMethods([ + 'setMagicInCookie', + ]) + ->getMock(); + + \OC_User::setIncognitoMode(false); } public function testGetUser() { @@ -100,12 +125,12 @@ class SessionTest extends \Test\TestCase { ->method('updateTokenActivity') ->with($token); - $manager->expects($this->any()) + $manager->expects($this->once()) ->method('get') ->with($expectedUser->getUID()) ->will($this->returnValue($expectedUser)); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $user = $userSession->getUser(); $this->assertSame($expectedUser, $user); $this->assertSame(10000, $token->getLastCheck()); @@ -127,7 +152,7 @@ class SessionTest extends \Test\TestCase { $manager = $this->createMock(Manager::class); $userSession = $this->getMockBuilder(Session::class) - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->setMethods([ 'getUser' ]) @@ -154,7 +179,7 @@ class SessionTest extends \Test\TestCase { ->method('getUID') ->will($this->returnValue('foo')); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $userSession->setUser($user); } @@ -181,17 +206,10 @@ class SessionTest extends \Test\TestCase { }, 'foo')); $managerMethods = get_class_methods(Manager::class); - //keep following methods intact in order to ensure hooks are - //working - $doNotMock = array('__construct', 'emit', 'listen'); - foreach ($doNotMock as $methodName) { - $i = array_search($methodName, $managerMethods, true); - if ($i !== false) { - unset($managerMethods[$i]); - } - } + //keep following methods intact in order to ensure hooks are working + $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']); $manager = $this->getMockBuilder(Manager::class) - ->setMethods($managerMethods) + ->setMethods($mockedManagerMethods) ->setConstructorArgs([$this->config]) ->getMock(); @@ -213,7 +231,7 @@ class SessionTest extends \Test\TestCase { ->will($this->returnValue($user)); $userSession = $this->getMockBuilder(Session::class) - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->setMethods([ 'prepareUserLogin' ]) @@ -238,18 +256,11 @@ class SessionTest extends \Test\TestCase { ->with('bar') ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException())); - $managerMethods = get_class_methods('\OC\User\Manager'); - //keep following methods intact in order to ensure hooks are - //working - $doNotMock = array('__construct', 'emit', 'listen'); - foreach ($doNotMock as $methodName) { - $i = array_search($methodName, $managerMethods, true); - if ($i !== false) { - unset($managerMethods[$i]); - } - } + $managerMethods = get_class_methods(\OC\User\Manager::class); + //keep following methods intact in order to ensure hooks are working + $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']); $manager = $this->getMockBuilder(Manager::class) - ->setMethods($managerMethods) + ->setMethods($mockedManagerMethods) ->setConstructorArgs([$this->config]) ->getMock(); @@ -267,28 +278,21 @@ class SessionTest extends \Test\TestCase { ->with('foo', 'bar') ->will($this->returnValue($user)); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $userSession->login('foo', 'bar'); } public function testLoginInvalidPassword() { $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock(); - $managerMethods = get_class_methods('\OC\User\Manager'); - //keep following methods intact in order to ensure hooks are - //working - $doNotMock = array('__construct', 'emit', 'listen'); - foreach ($doNotMock as $methodName) { - $i = array_search($methodName, $managerMethods, true); - if ($i !== false) { - unset($managerMethods[$i]); - } - } + $managerMethods = get_class_methods(\OC\User\Manager::class); + //keep following methods intact in order to ensure hooks are working + $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']); $manager = $this->getMockBuilder(Manager::class) - ->setMethods($managerMethods) + ->setMethods($mockedManagerMethods) ->setConstructorArgs([$this->config]) ->getMock(); $backend = $this->createMock(\Test\Util\User\Dummy::class); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock(); @@ -317,7 +321,7 @@ class SessionTest extends \Test\TestCase { public function testLoginNonExisting() { $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock(); $manager = $this->createMock(Manager::class); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $session->expects($this->never()) ->method('set'); @@ -343,7 +347,7 @@ class SessionTest extends \Test\TestCase { public function testLoginWithDifferentTokenLoginName() { $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock(); $manager = $this->createMock(Manager::class); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $username = 'user123'; $token = new \OC\Authentication\Token\DefaultToken(); $token->setLoginName($username); @@ -375,7 +379,7 @@ class SessionTest extends \Test\TestCase { /** @var \OC\User\Session $userSession */ $userSession = $this->getMockBuilder(Session::class) - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->setMethods(['login', 'supportsCookies', 'createSessionToken', 'getUser']) ->getMock(); @@ -411,7 +415,7 @@ class SessionTest extends \Test\TestCase { /** @var Session $userSession */ $userSession = $this->getMockBuilder(Session::class) - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->setMethods(['login', 'supportsCookies', 'createSessionToken', 'getUser']) ->getMock(); @@ -434,7 +438,7 @@ class SessionTest extends \Test\TestCase { /** @var \OC\User\Session $userSession */ $userSession = $this->getMockBuilder(Session::class) - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->setMethods(['isTokenPassword', 'login', 'supportsCookies', 'createSessionToken', 'getUser']) ->getMock(); @@ -476,7 +480,7 @@ class SessionTest extends \Test\TestCase { /** @var \OC\User\Session $userSession */ $userSession = $this->getMockBuilder(Session::class) - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->setMethods(['login', 'isTwoFactorEnforced']) ->getMock(); @@ -513,156 +517,216 @@ class SessionTest extends \Test\TestCase { public function testRememberLoginValidToken() { $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock(); - $session->expects($this->exactly(1)) - ->method('set') - ->with($this->callback(function ($key) { - switch ($key) { - case 'user_id': - return true; - default: - return false; - } - }, 'foo')); - $session->expects($this->once()) - ->method('regenerateId'); - - $managerMethods = get_class_methods(Manager::class); - //keep following methods intact in order to ensure hooks are - //working - $doNotMock = array('__construct', 'emit', 'listen'); - foreach ($doNotMock as $methodName) { - $i = array_search($methodName, $managerMethods, true); - if ($i !== false) { - unset($managerMethods[$i]); - } - } + $managerMethods = get_class_methods(\OC\User\Manager::class); + //keep following methods intact in order to ensure hooks are working + $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']); $manager = $this->getMockBuilder(Manager::class) - ->setMethods($managerMethods) + ->setMethods($mockedManagerMethods) ->setConstructorArgs([$this->config]) ->getMock(); + $userSession = $this->getMockBuilder(Session::class) + //override, otherwise tests will fail because of setcookie() + ->setMethods(['setMagicInCookie']) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) + ->getMock(); - $backend = $this->createMock(\Test\Util\User\Dummy::class); + $user = $this->createMock(IUser::class); + $token = 'goodToken'; + $oldSessionId = 'sess321'; + $sessionId = 'sess123'; - $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock(); + $session->expects($this->once()) + ->method('regenerateId'); + $manager->expects($this->once()) + ->method('get') + ->with('foo') + ->will($this->returnValue($user)); + $this->config->expects($this->once()) + ->method('getUserKeys') + ->with('foo', 'login_token') + ->will($this->returnValue([$token])); + $this->config->expects($this->once()) + ->method('deleteUserValue') + ->with('foo', 'login_token', $token); + $this->random->expects($this->once()) + ->method('generate') + ->with(32) + ->will($this->returnValue('abcdefg123456')); + $this->config->expects($this->once()) + ->method('setUserValue') + ->with('foo', 'login_token', 'abcdefg123456', 10000); + + $session->expects($this->once()) + ->method('getId') + ->will($this->returnValue($sessionId)); + $this->tokenProvider->expects($this->once()) + ->method('renewSessionToken') + ->with($oldSessionId, $sessionId) + ->will($this->returnValue(true)); $user->expects($this->any()) ->method('getUID') ->will($this->returnValue('foo')); + $userSession->expects($this->once()) + ->method('setMagicInCookie'); $user->expects($this->once()) ->method('updateLastLoginTimestamp'); + $session->expects($this->once()) + ->method('set') + ->with('user_id', 'foo'); - $manager->expects($this->once()) - ->method('get') - ->with('foo') - ->will($this->returnValue($user)); + $granted = $userSession->loginWithCookie('foo', $token, $oldSessionId); - //prepare login token - $token = 'goodToken'; - \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time()); + $this->assertTrue($granted); + } + public function testRememberLoginInvalidSessionToken() { + $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock(); + $managerMethods = get_class_methods(\OC\User\Manager::class); + //keep following methods intact in order to ensure hooks are working + $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']); + $manager = $this->getMockBuilder(Manager::class) + ->setMethods($mockedManagerMethods) + ->setConstructorArgs([$this->config]) + ->getMock(); $userSession = $this->getMockBuilder(Session::class) //override, otherwise tests will fail because of setcookie() ->setMethods(['setMagicInCookie']) - //there are passed as parameters to the constructor - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->getMock(); - $granted = $userSession->loginWithCookie('foo', $token); - - $this->assertSame($granted, true); - } + $user = $this->createMock(IUser::class); + $token = 'goodToken'; + $oldSessionId = 'sess321'; + $sessionId = 'sess123'; - public function testRememberLoginInvalidToken() { - $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock(); - $session->expects($this->never()) - ->method('set'); $session->expects($this->once()) ->method('regenerateId'); + $manager->expects($this->once()) + ->method('get') + ->with('foo') + ->will($this->returnValue($user)); + $this->config->expects($this->once()) + ->method('getUserKeys') + ->with('foo', 'login_token') + ->will($this->returnValue([$token])); + $this->config->expects($this->once()) + ->method('deleteUserValue') + ->with('foo', 'login_token', $token); + $this->config->expects($this->once()) + ->method('setUserValue'); // TODO: mock new random value - $managerMethods = get_class_methods('\OC\User\Manager'); - //keep following methods intact in order to ensure hooks are - //working - $doNotMock = array('__construct', 'emit', 'listen'); - foreach ($doNotMock as $methodName) { - $i = array_search($methodName, $managerMethods, true); - if ($i !== false) { - unset($managerMethods[$i]); - } - } - $manager = $this->getMockBuilder(Manager::class) - ->setMethods($managerMethods) - ->setConstructorArgs([$this->config]) - ->getMock(); - - $backend = $this->createMock(\Test\Util\User\Dummy::class); - - $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock(); + $session->expects($this->once()) + ->method('getId') + ->will($this->returnValue($sessionId)); + $this->tokenProvider->expects($this->once()) + ->method('renewSessionToken') + ->with($oldSessionId, $sessionId) + ->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException())); - $user->expects($this->any()) + $user->expects($this->never()) ->method('getUID') ->will($this->returnValue('foo')); + $userSession->expects($this->never()) + ->method('setMagicInCookie'); $user->expects($this->never()) ->method('updateLastLoginTimestamp'); + $session->expects($this->never()) + ->method('set') + ->with('user_id', 'foo'); + $granted = $userSession->loginWithCookie('foo', $token, $oldSessionId); + + $this->assertFalse($granted); + } + + public function testRememberLoginInvalidToken() { + $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock(); + $managerMethods = get_class_methods(\OC\User\Manager::class); + //keep following methods intact in order to ensure hooks are working + $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']); + $manager = $this->getMockBuilder(Manager::class) + ->setMethods($mockedManagerMethods) + ->setConstructorArgs([$this->config]) + ->getMock(); + $userSession = $this->getMockBuilder(Session::class) + //override, otherwise tests will fail because of setcookie() + ->setMethods(['setMagicInCookie']) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) + ->getMock(); + + $user = $this->createMock(IUser::class); + $token = 'goodToken'; + $oldSessionId = 'sess321'; + + $session->expects($this->once()) + ->method('regenerateId'); $manager->expects($this->once()) ->method('get') ->with('foo') ->will($this->returnValue($user)); + $this->config->expects($this->once()) + ->method('getUserKeys') + ->with('foo', 'login_token') + ->will($this->returnValue(['anothertoken'])); + $this->config->expects($this->never()) + ->method('deleteUserValue') + ->with('foo', 'login_token', $token); + + $this->tokenProvider->expects($this->never()) + ->method('renewSessionToken'); + $userSession->expects($this->never()) + ->method('setMagicInCookie'); + $user->expects($this->never()) + ->method('updateLastLoginTimestamp'); + $session->expects($this->never()) + ->method('set') + ->with('user_id', 'foo'); - //prepare login token - $token = 'goodToken'; - \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time()); - - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); - $granted = $userSession->loginWithCookie('foo', 'badToken'); + $granted = $userSession->loginWithCookie('foo', $token, $oldSessionId); - $this->assertSame($granted, false); + $this->assertFalse($granted); } public function testRememberLoginInvalidUser() { $session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock(); - $session->expects($this->never()) - ->method('set'); - $session->expects($this->once()) - ->method('regenerateId'); - - $managerMethods = get_class_methods('\OC\User\Manager'); - //keep following methods intact in order to ensure hooks are - //working - $doNotMock = array('__construct', 'emit', 'listen'); - foreach ($doNotMock as $methodName) { - $i = array_search($methodName, $managerMethods, true); - if ($i !== false) { - unset($managerMethods[$i]); - } - } + $managerMethods = get_class_methods(\OC\User\Manager::class); + //keep following methods intact in order to ensure hooks are working + $mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']); $manager = $this->getMockBuilder(Manager::class) - ->setMethods($managerMethods) + ->setMethods($mockedManagerMethods) ->setConstructorArgs([$this->config]) ->getMock(); + $userSession = $this->getMockBuilder(Session::class) + //override, otherwise tests will fail because of setcookie() + ->setMethods(['setMagicInCookie']) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) + ->getMock(); + $token = 'goodToken'; + $oldSessionId = 'sess321'; - $backend = $this->createMock(\Test\Util\User\Dummy::class); - - $user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock(); - - $user->expects($this->never()) - ->method('getUID'); - $user->expects($this->never()) - ->method('updateLastLoginTimestamp'); - + $session->expects($this->once()) + ->method('regenerateId'); $manager->expects($this->once()) ->method('get') ->with('foo') ->will($this->returnValue(null)); + $this->config->expects($this->never()) + ->method('getUserKeys') + ->with('foo', 'login_token') + ->will($this->returnValue(['anothertoken'])); + + $this->tokenProvider->expects($this->never()) + ->method('renewSessionToken'); + $userSession->expects($this->never()) + ->method('setMagicInCookie'); + $session->expects($this->never()) + ->method('set') + ->with('user_id', 'foo'); - //prepare login token - $token = 'goodToken'; - \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time()); - - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); - $granted = $userSession->loginWithCookie('foo', $token); + $granted = $userSession->loginWithCookie('foo', $token, $oldSessionId); - $this->assertSame($granted, false); + $this->assertFalse($granted); } public function testActiveUserAfterSetSession() { @@ -684,7 +748,7 @@ class SessionTest extends \Test\TestCase { $session = new Memory(''); $session->set('user_id', 'foo'); $userSession = $this->getMockBuilder('\OC\User\Session') - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->setMethods([ 'validateSession' ]) @@ -705,7 +769,7 @@ class SessionTest extends \Test\TestCase { $session = $this->createMock(ISession::class); $token = $this->createMock(IToken::class); $user = $this->createMock(IUser::class); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $random = $this->createMock(ISecureRandom::class); $config = $this->createMock(IConfig::class); @@ -749,7 +813,7 @@ class SessionTest extends \Test\TestCase { $session = $this->createMock(ISession::class); $token = $this->createMock(IToken::class); $user = $this->createMock(IUser::class); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $random = $this->createMock(ISecureRandom::class); $config = $this->createMock(IConfig::class); @@ -796,7 +860,7 @@ class SessionTest extends \Test\TestCase { ->disableOriginalConstructor() ->getMock(); $session = $this->createMock(ISession::class); - $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config); + $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random); $request = $this->createMock(IRequest::class); $uid = 'user123'; @@ -826,7 +890,7 @@ class SessionTest extends \Test\TestCase { $user = $this->createMock(IUser::class); $userSession = $this->getMockBuilder('\OC\User\Session') ->setMethods(['logout']) - ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config]) + ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config, $this->random]) ->getMock(); $request = $this->createMock(IRequest::class); @@ -855,7 +919,7 @@ class SessionTest extends \Test\TestCase { $timeFactory = $this->createMock(ITimeFactory::class); $tokenProvider = $this->createMock(IProvider::class); $userSession = $this->getMockBuilder('\OC\User\Session') - ->setConstructorArgs([$userManager, $session, $timeFactory, $tokenProvider, $this->config]) + ->setConstructorArgs([$userManager, $session, $timeFactory, $tokenProvider, $this->config, $this->random]) ->setMethods(['logout']) ->getMock(); @@ -902,7 +966,7 @@ class SessionTest extends \Test\TestCase { $timeFactory = $this->createMock(ITimeFactory::class); $tokenProvider = $this->createMock(IProvider::class); $userSession = $this->getMockBuilder('\OC\User\Session') - ->setConstructorArgs([$userManager, $session, $timeFactory, $tokenProvider, $this->config]) + ->setConstructorArgs([$userManager, $session, $timeFactory, $tokenProvider, $this->config, $this->random]) ->setMethods(['logout']) ->getMock(); @@ -936,7 +1000,7 @@ class SessionTest extends \Test\TestCase { $session = $this->createMock(ISession::class); $timeFactory = $this->createMock(ITimeFactory::class); $tokenProvider = $this->createMock(IProvider::class); - $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config); + $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config, $this->random); $password = '123456'; $sessionId = 'session1234'; @@ -961,7 +1025,7 @@ class SessionTest extends \Test\TestCase { $session = $this->createMock(ISession::class); $timeFactory = $this->createMock(ITimeFactory::class); $tokenProvider = $this->createMock(IProvider::class); - $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config); + $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config, $this->random); $session->expects($this->once()) ->method('getId') @@ -975,7 +1039,7 @@ class SessionTest extends \Test\TestCase { $session = $this->createMock(ISession::class); $timeFactory = $this->createMock(ITimeFactory::class); $tokenProvider = $this->createMock(IProvider::class); - $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config); + $userSession = new \OC\User\Session($userManager, $session, $timeFactory, $tokenProvider, $this->config, $this->random); $password = '123456'; $sessionId = 'session1234'; @@ -1015,7 +1079,7 @@ class SessionTest extends \Test\TestCase { $tokenProvider = new DefaultTokenProvider($mapper, $crypto, $this->config, $logger, $this->timeFactory); /** @var \OC\User\Session $userSession */ - $userSession = new Session($manager, $session, $this->timeFactory, $tokenProvider, $this->config); + $userSession = new Session($manager, $session, $this->timeFactory, $tokenProvider, $this->config, $this->random); $mapper->expects($this->any()) ->method('getToken') @@ -1065,7 +1129,7 @@ class SessionTest extends \Test\TestCase { $tokenProvider = new DefaultTokenProvider($mapper, $crypto, $this->config, $logger, $this->timeFactory); /** @var \OC\User\Session $userSession */ - $userSession = new Session($manager, $session, $this->timeFactory, $tokenProvider, $this->config); + $userSession = new Session($manager, $session, $this->timeFactory, $tokenProvider, $this->config, $this->random); $mapper->expects($this->any()) ->method('getToken') @@ -1092,4 +1156,27 @@ class SessionTest extends \Test\TestCase { $userSession->logClientIn('john', 'doe', $request, $this->throttler); } + + public function testCreateRememberMeToken() { + $user = $this->createMock(IUser::class); + $user + ->expects($this->exactly(2)) + ->method('getUID') + ->willReturn('UserUid'); + $this->random + ->expects($this->once()) + ->method('generate') + ->with(32) + ->willReturn('LongRandomToken'); + $this->config + ->expects($this->once()) + ->method('setUserValue') + ->with('UserUid', 'login_token', 'LongRandomToken', 10000); + $this->userSession + ->expects($this->once()) + ->method('setMagicInCookie') + ->with('UserUid', 'LongRandomToken'); + + $this->userSession->createRememberMeToken($user); + } } |