diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 178a3da3100a..9c4f29020bf5 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -78,8 +78,6 @@ * - preLogin(string $user, string $password) * - postLogin(\OC\User\User $user, string $password) * - failedLogin(string $user) - * - preRememberedLogin(string $uid) - * - postRememberedLogin(\OC\User\User $user) * - logout() * - postLogout() * @@ -530,38 +528,12 @@ public function tryBasicAuthLogin(IRequest $request) { * compatibility. */ private function loginWithPassword($login, $password) { - $beforeEvent = new GenericEvent(null, ['loginType' => 'password', 'login' => $login, 'uid' => $login, '_uid' => 'deprecated: please use \'login\', the real uid is not yet known', 'password' => $password]); - $this->eventDispatcher->dispatch($beforeEvent, 'user.beforelogin'); - $this->manager->emit('\OC\User', 'preLogin', [$login, $password]); - $user = $this->manager->checkPassword($login, $password); if ($user === false) { $this->emitFailedLogin($login); return false; } - - if ($user->isEnabled()) { - $this->setUser($user); - $this->setLoginName($login); - $firstTimeLogin = $user->getLastLogin() === 0; - $this->manager->emit('\OC\User', 'postLogin', [$user, $password]); - $afterEvent = new GenericEvent(null, ['loginType' => 'password', 'user' => $user, 'uid' => $user->getUID(), 'password' => $password]); - $this->eventDispatcher->dispatch($afterEvent, 'user.afterlogin'); - - if ($this->isLoggedIn()) { - $this->prepareUserLogin($firstTimeLogin); - $user->updateLastLoginTimestamp(); - return true; - } - - // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory - $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); - throw new LoginException($message); - } - - // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory - $message = \OC::$server->getL10N('lib')->t('User disabled'); - throw new LoginException($message); + return $this->loginInOwnCloud('password', $user, $password); } /** @@ -588,42 +560,21 @@ private function loginWithToken($token) { // Ignore and use empty string instead } - $this->manager->emit('\OC\User', 'preLogin', [$uid, $password]); - $beforeEvent = new GenericEvent(null, ['loginType' => 'token', 'login' => $uid, 'uid' => $uid, 'password' => $password]); - $this->eventDispatcher->dispatch($beforeEvent, 'user.beforelogin'); - $user = $this->manager->get($uid); if ($user === null) { // user does not exist $this->emitFailedLogin($uid); return false; } - if (!$user->isEnabled()) { - // disabled users can not log in - // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory - $message = \OC::$server->getL10N('lib')->t('User disabled'); - throw new LoginException($message); - } - //login - $this->setUser($user); - $this->setLoginName($dbToken->getLoginName()); - $this->manager->emit('\OC\User', 'postLogin', [$user, $password]); - $afterEvent = new GenericEvent(null, ['loginType' => 'token', 'user' => $user, 'login' => $user->getUID(), 'uid' => $user->getUID(), 'password' => $password]); - $this->eventDispatcher->dispatch($afterEvent, 'user.afterlogin'); - - if ($this->isLoggedIn()) { - $this->prepareUserLogin(); - } else { - // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory - $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); - throw new LoginException($message); - } + $loginOk = $this->loginInOwnCloud('token', $user, $password); // set the app password - $this->session->set('app_password', $token); + if ($loginOk) { + $this->session->set('app_password', $token); + } - return true; + return $loginOk; } /** @@ -670,10 +621,6 @@ public function loginWithApache(IApacheBackend $apacheBackend) { ); $this->session->regenerateId(); - $this->manager->emit('\OC\User', 'preLogin', [$uid, '']); - $beforeEvent = new GenericEvent(null, ['loginType' => 'apache', 'login' => $uid, 'uid' => $uid, 'password' => '']); - $this->eventDispatcher->dispatch($beforeEvent, 'user.beforelogin'); - // Die here if not valid if (!$apacheBackend->isSessionActive()) { return false; @@ -688,38 +635,12 @@ public function loginWithApache(IApacheBackend $apacheBackend) { return false; } - if ($user->isEnabled()) { - $this->setUser($user); - $this->setLoginName($uid); - + $loginOk = $this->loginInOwnCloud('apache', $user, ''); + if ($loginOk) { $request = OC::$server->getRequest(); $this->createSessionToken($request, $uid, $uid); - - // setup the filesystem - OC_Util::setupFS($uid); - // first call the post_login hooks, the login-process needs to be - // completed before we can safely create the users folder. - // For example encryption needs to initialize the users keys first - // before we can create the user folder with the skeleton files - - $firstTimeLogin = $user->getLastLogin() === 0; - $this->manager->emit('\OC\User', 'postLogin', [$user, '']); - $afterEvent = new GenericEvent(null, ['loginType' => 'apache', 'user' => $user, 'login' => $user->getUID(), 'uid' => $user->getUID(), 'password' => '']); - $this->eventDispatcher->dispatch($afterEvent, 'user.afterlogin'); - if ($this->isLoggedIn()) { - $this->prepareUserLogin($firstTimeLogin); - $user->updateLastLoginTimestamp(); - return true; - } - - // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory - $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); - throw new LoginException($message); } - - // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory - $message = \OC::$server->getL10N('lib')->t('User disabled'); - throw new LoginException($message); + return $loginOk; } /** @@ -973,13 +894,10 @@ public function tryTokenLogin(IRequest $request) { $token = \substr($authHeader, 6); } - if (!$this->loginWithToken($token)) { - return false; + if ($this->validateToken($token)) { + return $this->loginWithToken($token); } - if (!$this->validateToken($token)) { - return false; - } - return true; + return false; } public function tryRememberMeLogin(IRequest $request) { @@ -1019,9 +937,9 @@ public function tryAuthModuleLogin(IRequest $request) { } $uid = $user->getUID(); $password = $authModule->getUserPassword($request); - $this->createSessionToken($request, $uid, $uid, $password); - $loginOk = $this->loginUser($user, $password); + $loginOk = $this->loginUser($user, $password, \get_class($authModule)); if ($loginOk) { + $this->createSessionToken($request, $uid, $uid, $password); $this->session->set(Auth::DAV_AUTHENTICATED, $uid); } return $loginOk; @@ -1039,45 +957,9 @@ public function tryAuthModuleLogin(IRequest $request) { * @return boolean True if the user can be authenticated, false otherwise * @throws LoginException if an app canceled the login process or the user is not enabled */ - public function loginUser(IUser $user = null, $password = null) { - $uid = $user === null ? '' : $user->getUID(); - return $this->emittingCall( - function () use (&$user, &$password) { - if ($user === null) { - //Cannot extract the uid when $user is null, hence pass null - $this->emitFailedLogin(null); - return false; - } - - $this->manager->emit('\OC\User', 'preLogin', [$user->getUID(), $password]); - - if (!$user->isEnabled()) { - $message = \OC::$server->getL10N('lib')->t('User disabled'); - $this->emitFailedLogin($user->getUID()); - throw new LoginException($message); - } - - $this->setUser($user); - $this->setLoginName($user->getDisplayName()); - $firstTimeLogin = $user->getLastLogin() === 0; - - $this->manager->emit('\OC\User', 'postLogin', [$user, $password]); - - if ($this->isLoggedIn()) { - $this->prepareUserLogin($firstTimeLogin); - $user->updateLastLoginTimestamp(); - } else { - $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); - throw new LoginException($message); - } - - return true; - }, - ['before' => ['user' => $user, 'login' => $uid, 'uid' => $uid, 'password' => $password], - 'after' => ['user' => $user, 'login' => $uid, 'uid' => $uid, 'password' => $password]], - 'user', - 'login' - ); + public function loginUser(IUser $user = null, $password = null, $authModuleClass = null) { + // openidconnect calls the loginUser method. It might not have an $authModuleClass + return $this->loginInOwnCloud($authModuleClass, $user, $password); } /** @@ -1094,18 +976,12 @@ public function loginWithCookie($uid, $currentToken) { ['app' => __METHOD__, 'uid' => $uid, 'currentToken' => $currentToken] ); $this->session->regenerateId(); - $this->manager->emit('\OC\User', 'preRememberedLogin', [$uid]); $user = $this->manager->get($uid); if ($user === null) { // user does not exist return false; } - if (!$user->isEnabled()) { - $message = \OC::$server->getL10N('lib')->t('User disabled'); - throw new LoginException($message); - } - $hashedToken = \hash('snefru', $currentToken); // get stored tokens $storedTokenTime = $this->config->getUserValue($uid, 'login_token', $hashedToken, null); @@ -1124,21 +1000,58 @@ public function loginWithCookie($uid, $currentToken) { } //login - $this->setUser($user); - $this->setLoginName($user->getDisplayName()); - $this->manager->emit('\OC\User', 'postRememberedLogin', [$user]); + $loginOk = $this->loginInOwnCloud('cookie', $user, null, ['ignoreEvents' => true]); + + // replace successfully used token with a new one + if ($loginOk) { + $this->setNewRememberMeTokenForLoggedInUser(); + } - if (!$this->isLoggedIn()) { + return $loginOk; + } + + /** + * @return bool true if logged in, false otherwise + * @throws LoginException + */ + private function loginInOwnCloud($loginType, $user, $password, $options = []) { + $login = $user->getUID(); + + if (!isset($options['ignoreEvents']) || !$options['ignoreEvents'] === true) { + // loginWithCookie won't trigger these events + $beforeEvent = new GenericEvent(null, ['loginType' => $loginType, 'login' => $login, 'uid' => $login, '_uid' => 'deprecated: please use \'login\', the real uid is not yet known', 'password' => $password]); + $this->eventDispatcher->dispatch($beforeEvent, 'user.beforelogin'); + $this->manager->emit('\OC\User', 'preLogin', [$login, $password]); + } + + $this->logger->info("login {$user->getUID()} using \"$loginType\" login type", ['app' => __METHOD__]); + + if ($user->isEnabled()) { + $this->setUser($user); + $this->setLoginName($login); + $firstTimeLogin = $user->getLastLogin() === 0; + + if (!isset($options['ignoreEvents']) || !$options['ignoreEvents'] === true) { + // loginWithCookie won't trigger these events + $this->manager->emit('\OC\User', 'postLogin', [$user, $password]); + $afterEvent = new GenericEvent(null, ['loginType' => $loginType, 'user' => $user, 'uid' => $user->getUID(), 'password' => $password]); + $this->eventDispatcher->dispatch($afterEvent, 'user.afterlogin'); + } + + if ($this->isLoggedIn()) { + $this->prepareUserLogin($firstTimeLogin); + $user->updateLastLoginTimestamp(); + return true; + } + + // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); throw new LoginException($message); } - // replace successfully used token with a new one - $this->setNewRememberMeTokenForLoggedInUser(); - - $this->prepareUserLogin(); // this shouldn't be the first time logging in. - $user->updateLastLoginTimestamp(); - return true; + // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory + $message = \OC::$server->getL10N('lib')->t('User disabled'); + throw new LoginException($message); } public function setNewRememberMeTokenForLoggedInUser() {