diff options
author | Thomas Steur <tsteur@users.noreply.github.com> | 2020-03-18 06:04:12 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-18 06:04:12 +0300 |
commit | f0c246cb3a4db3021da7552f6779d56613799414 (patch) | |
tree | 42ddf7a9c2e086df78ffc40dfc23af74f8dd3a39 /plugins/Login | |
parent | e493fee87c983e02001a7d9438cefe58141a38af (diff) |
App specific token_auths (#15410)
* some initial work
* add security page
* backing up some code
* more functionality
* adjust more UI parts
* adjust more code
* more tweaks
* add todo note
* few tweaks
* make sure date is in right format
* fix not existing column
* few fixes
* available hashes
* use different hash algo so tests run on php 5
* fix name of aglorithm
* trying to fix some tests
* another try to fix some tests
* more fixes
* more fixes
* few fixes
* update template
* fix some tests
* fix test
* fixing some tests
* various test fixes
* more fixes
* few more tests
* more tests
* various tweaks
* add translations
* add some ui tests
* fix selector
* tweaks
* trying to fix some ui tests
* fallback to regular authentication if needed
* fix call authenticate on null
* fix user settings
* fix some tests
* few fixes
* fix more ui tests
* update schema
* Update plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js
Co-Authored-By: Stefan Giehl <stefan@matomo.org>
* fix maps are not showing data
* trying to fix some tests
* set correct token
* trying to fix tracking failure
* minor tweaks and fixes
* fix more tests
* fix screenshot test
* trigger event so brute force logic is executed
* test no fallback to actual authentication
* allow fallback
* apply review feedback
* fix some tests
* fix tests
* make sure location values from query params are limited properly before attempting a db insert
* make sure plugin uninstall migration reloads plugins, make sure 4.0.0-b1 migration removes unique index that is no longer used, use defaults extra file in SqlDump to get test to run on travis
* Fix UI tests.
* update expected screenshot
Co-authored-by: Stefan Giehl <stefan@matomo.org>
Co-authored-by: diosmosis <diosmosis@users.noreply.github.com>
Diffstat (limited to 'plugins/Login')
-rw-r--r-- | plugins/Login/Auth.php | 21 | ||||
-rw-r--r-- | plugins/Login/Login.php | 2 | ||||
-rw-r--r-- | plugins/Login/SessionInitializer.php | 2 | ||||
-rw-r--r-- | plugins/Login/tests/Integration/LoginTest.php | 26 | ||||
-rw-r--r-- | plugins/Login/tests/Integration/SessionInitializerTest.php | 4 | ||||
-rw-r--r-- | plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_noentries.png | 4 | ||||
-rw-r--r-- | plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_withentries.png | 4 |
7 files changed, 40 insertions, 23 deletions
diff --git a/plugins/Login/Auth.php b/plugins/Login/Auth.php index 3d572abcf9..a196b48b15 100644 --- a/plugins/Login/Auth.php +++ b/plugins/Login/Auth.php @@ -10,6 +10,7 @@ namespace Piwik\Plugins\Login; use Piwik\AuthResult; use Piwik\Auth\Password; +use Piwik\Date; use Piwik\Piwik; use Piwik\Plugins\UsersManager\Model; use Piwik\Plugins\UsersManager\UsersManager; @@ -76,8 +77,9 @@ class Auth implements \Piwik\Auth if ($this->passwordHelper->needsRehash($user['password'])) { $newPasswordHash = $this->passwordHelper->hash($passwordHash); - $this->userModel->updateUser($login, $newPasswordHash, $user['email'], $user['alias'], $user['token_auth']); + $this->userModel->updateUser($login, $newPasswordHash, $user['email'], $user['alias']); } + $this->token_auth = null; // make sure to generate a random token return $this->authenticationSuccess($user); } @@ -90,6 +92,7 @@ class Auth implements \Piwik\Auth $user = $this->userModel->getUserByTokenAuth($token); if (!empty($user['login'])) { + $this->userModel->setTokenAuthWasUsed($token, Date::now()->getDatetime()); return $this->authenticationSuccess($user); } @@ -98,13 +101,10 @@ class Auth implements \Piwik\Auth private function authenticateWithLoginAndToken($token, $login) { - $user = $this->userModel->getUser($login); + $user = $this->userModel->getUserByTokenAuth($token); - if (!empty($user['token_auth']) - // authenticate either with the token or the "hash token" - && ((SessionInitializer::getHashTokenAuth($login, $user['token_auth']) === $token) - || $user['token_auth'] === $token) - ) { + if (!empty($user['login']) && $user['login'] === $login) { + $this->userModel->setTokenAuthWasUsed($token, Date::now()->getDatetime()); return $this->authenticationSuccess($user); } @@ -113,12 +113,15 @@ class Auth implements \Piwik\Auth private function authenticationSuccess(array $user) { - $this->setTokenAuth($user['token_auth']); + if (empty($this->token_auth)) { + $this->token_auth = $this->userModel->generateRandomTokenAuth(); + // we generated one randomly which will then be stored in the session and used across the session + } $isSuperUser = (int) $user['superuser_access']; $code = $isSuperUser ? AuthResult::SUCCESS_SUPERUSER_AUTH_CODE : AuthResult::SUCCESS; - return new AuthResult($code, $user['login'], $user['token_auth']); + return new AuthResult($code, $user['login'], $this->token_auth); } /** diff --git a/plugins/Login/Login.php b/plugins/Login/Login.php index d60358c709..9f6ed6f820 100644 --- a/plugins/Login/Login.php +++ b/plugins/Login/Login.php @@ -41,7 +41,7 @@ class Login extends \Piwik\Plugin // for brute force prevention of all tracking + reporting api requests 'Request.initAuthenticationObject' => 'onInitAuthenticationObject', - 'API.UsersManager.getTokenAuth' => 'beforeLoginCheckBruteForce', // doesn't require auth but can be used to authenticate + 'API.UsersManager.createAppSpecificTokenAuth' => 'beforeLoginCheckBruteForce', // doesn't require auth but can be used to authenticate // for brute force prevention of all UI requests 'Controller.Login.logme' => 'beforeLoginCheckBruteForce', diff --git a/plugins/Login/SessionInitializer.php b/plugins/Login/SessionInitializer.php index 0b31f62114..b997358a4b 100644 --- a/plugins/Login/SessionInitializer.php +++ b/plugins/Login/SessionInitializer.php @@ -182,8 +182,6 @@ class SessionInitializer protected function processSuccessfulSession(AuthResult $authResult, $rememberMe) { $cookie = $this->getAuthCookie($rememberMe); - $cookie->set('login', $authResult->getIdentity()); - $cookie->set('token_auth', $this->getHashTokenAuth($authResult->getIdentity(), $authResult->getTokenAuth())); $cookie->setSecure(ProxyHttp::isHttps()); $cookie->setHttpOnly(true); $cookie->save(); diff --git a/plugins/Login/tests/Integration/LoginTest.php b/plugins/Login/tests/Integration/LoginTest.php index a0351b5ea1..8a45a53096 100644 --- a/plugins/Login/tests/Integration/LoginTest.php +++ b/plugins/Login/tests/Integration/LoginTest.php @@ -11,6 +11,7 @@ namespace Piwik\Plugins\Login\tests\Integration; use Piwik\AuthResult; use Piwik\Common; use Piwik\Config; +use Piwik\Date; use Piwik\DbHelper; use Piwik\NoAccessException; use Piwik\Plugins\Login\Auth; @@ -243,6 +244,17 @@ class LoginTest extends IntegrationTestCase $this->assertSuperUserLogin($rc, 'user'); } + public function test_authenticate_successUserLoginAndTokenAuthWithAnonymous() + { + DbHelper::createAnonymousUser(); + + $user = $this->_setUpUser(); + + // valid login & token auth + $rc = $this->authenticate('anonymous', 'anonymous'); + $this->assertUserLogin($rc, 'anonymous', strlen('anonymous')); + } + public function test_authenticate_successUserLoginAndTokenAuth() { $user = $this->_setUpUser(); @@ -271,7 +283,8 @@ class LoginTest extends IntegrationTestCase $rc = $this->auth->authenticate(); $this->assertUserLogin($rc); // Check that the token auth is correct in the result - $this->assertEquals($user['tokenAuth'], $rc->getTokenAuth()); + $this->assertEquals(32, strlen($rc->getTokenAuth())); + $this->assertTrue(ctype_xdigit($rc->getTokenAuth())); } public function test_authenticate_successWithSuperUserPassword() @@ -307,7 +320,8 @@ class LoginTest extends IntegrationTestCase $rc = $this->auth->authenticate(); $this->assertUserLogin($rc); // Check that the token auth is correct in the result - $this->assertEquals($user['tokenAuth'], $rc->getTokenAuth()); + $this->assertEquals(32, strlen($rc->getTokenAuth())); + $this->assertTrue(ctype_xdigit($rc->getTokenAuth())); } /** @@ -324,7 +338,8 @@ class LoginTest extends IntegrationTestCase $this->assertUserLogin($rc); // Check that the login + token auth is correct in the result $this->assertEquals($user['login'], $rc->getIdentity()); - $this->assertEquals($user['tokenAuth'], $rc->getTokenAuth()); + $this->assertEquals(32, strlen($rc->getTokenAuth())); + $this->assertTrue(ctype_xdigit($rc->getTokenAuth())); } protected function _setUpUser() @@ -338,9 +353,10 @@ class LoginTest extends IntegrationTestCase API::getInstance()->addUser($user['login'], $user['password'], $user['email'], $user['alias']); $model = new \Piwik\Plugins\UsersManager\Model(); - $dbUser = $model->getUser($user['login']); + $tokenAuth = $model->generateRandomTokenAuth(); + $model->addTokenAuth($user['login'], $tokenAuth, 'many users test', Date::now()->getDatetime()); - $user['tokenAuth'] = $dbUser['token_auth']; + $user['tokenAuth'] = $tokenAuth; return $user; } diff --git a/plugins/Login/tests/Integration/SessionInitializerTest.php b/plugins/Login/tests/Integration/SessionInitializerTest.php index c2215de7a9..7be28c174c 100644 --- a/plugins/Login/tests/Integration/SessionInitializerTest.php +++ b/plugins/Login/tests/Integration/SessionInitializerTest.php @@ -36,6 +36,7 @@ class SessionInitializerTest extends IntegrationTestCase $this->assertAuthCookieIsAbsent(); $sessionInitializer = new TestSessionInitializer(); + $this->assertEmpty($sessionInitializer->cookie); $sessionInitializer->initSession($this->makeMockAuth(AuthResult::SUCCESS), true); $this->assertAuthCookieIsCreated($sessionInitializer->cookie); @@ -69,8 +70,7 @@ class SessionInitializerTest extends IntegrationTestCase private function assertAuthCookieIsCreated(Cookie $cookie) { - self::assertStringContainsString('login=czo5OiJ0ZXN0bG9naW4iOw==:token_auth=czozMjoiOWU5MDYxZjk2MDI0YTY3NWFmOGFkNWZmNmNiZGY2ZGMiOw==', - $cookie->generateContentString()); + $this->assertSame('', $cookie->generateContentString()); } private function createAuthCookie() diff --git a/plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_noentries.png b/plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_noentries.png index 02fe11e89e..7c129e3f46 100644 --- a/plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_noentries.png +++ b/plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_noentries.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:524375b5af2cbabc68f4973e66340276339deb907f9f0406a36f4fefc6fae014 -size 88970 +oid sha256:11249006c3f0eca81d59dc3b0334283d736d4d1e5c47ee698b53dc7a6b1acb2a +size 89496 diff --git a/plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_withentries.png b/plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_withentries.png index 93e8f1d9aa..0233d76503 100644 --- a/plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_withentries.png +++ b/plugins/Login/tests/UI/expected-screenshots/Login_bruteforcelog_withentries.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fa4a84825aafc43395995ee62a3f7d4830506381d782ddbd841168fee818cc3 -size 106683 +oid sha256:3e698b7fa581131093a71889d3fecee464d1f1ecb830a058aad8fa1fb3db8765 +size 107286 |