aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2019-05-03 15:09:19 +0200
committerChristoph Wurst <christoph@winzerhof-wurst.at>2019-05-07 18:04:36 +0200
commit170582d4f5eef1cc53c043d67c5d9d07d097155c (patch)
tree640d7a0c0fbfdf1d9a567c7fa5ddbb3cdb4f5316 /core
parent5893f218c247d4c0829fb74161e663f3903e15ad (diff)
downloadnextcloud-server-170582d4f5eef1cc53c043d67c5d9d07d097155c.tar.gz
nextcloud-server-170582d4f5eef1cc53c043d67c5d9d07d097155c.zip
Add a login chain to reduce the complexity of LoginController::tryLogin
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'core')
-rw-r--r--core/Controller/LoginController.php163
1 files changed, 37 insertions, 126 deletions
diff --git a/core/Controller/LoginController.php b/core/Controller/LoginController.php
index 85d3b6b837f..9c11a37639a 100644
--- a/core/Controller/LoginController.php
+++ b/core/Controller/LoginController.php
@@ -33,7 +33,8 @@
namespace OC\Core\Controller;
-use OC\Authentication\Token\IToken;
+use OC\Authentication\Login\Chain;
+use OC\Authentication\Login\LoginData;
use OC\Authentication\TwoFactorAuth\Manager;
use OC\Security\Bruteforce\Throttler;
use OC\User\Session;
@@ -44,17 +45,14 @@ use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
-use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Defaults;
use OCP\IConfig;
use OCP\ILogger;
use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
-use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
-use OC\Hooks\PublicEmitter;
use OCP\Util;
class LoginController extends Controller {
@@ -74,27 +72,14 @@ class LoginController extends Controller {
private $urlGenerator;
/** @var ILogger */
private $logger;
- /** @var Manager */
- private $twoFactorManager;
/** @var Defaults */
private $defaults;
/** @var Throttler */
private $throttler;
+ /** @var Chain */
+ private $loginChain;
- /**
- * @param string $appName
- * @param IRequest $request
- * @param IUserManager $userManager
- * @param IConfig $config
- * @param ISession $session
- * @param IUserSession $userSession
- * @param IURLGenerator $urlGenerator
- * @param ILogger $logger
- * @param Manager $twoFactorManager
- * @param Defaults $defaults
- * @param Throttler $throttler
- */
- public function __construct($appName,
+ public function __construct(?string $appName,
IRequest $request,
IUserManager $userManager,
IConfig $config,
@@ -102,9 +87,9 @@ class LoginController extends Controller {
IUserSession $userSession,
IURLGenerator $urlGenerator,
ILogger $logger,
- Manager $twoFactorManager,
Defaults $defaults,
- Throttler $throttler) {
+ Throttler $throttler,
+ Chain $loginChain) {
parent::__construct($appName, $request);
$this->userManager = $userManager;
$this->config = $config;
@@ -112,9 +97,9 @@ class LoginController extends Controller {
$this->userSession = $userSession;
$this->urlGenerator = $urlGenerator;
$this->logger = $logger;
- $this->twoFactorManager = $twoFactorManager;
$this->defaults = $defaults;
$this->throttler = $throttler;
+ $this->loginChain = $loginChain;
}
/**
@@ -226,8 +211,8 @@ class LoginController extends Controller {
* @param array $parameters
* @return array
*/
- private function setPasswordResetParameters(
- string $user = null, array $parameters): array {
+ private function setPasswordResetParameters(?string $user,
+ array $parameters): array {
if ($user !== null && $user !== '') {
$userObj = $this->userManager->get($user);
} else {
@@ -250,12 +235,8 @@ class LoginController extends Controller {
return $parameters;
}
- /**
- * @param string $redirectUrl
- * @return RedirectResponse
- */
- private function generateRedirect($redirectUrl) {
- if (!is_null($redirectUrl) && $this->userSession->isLoggedIn()) {
+ private function generateRedirect(?string $redirectUrl): RedirectResponse {
+ if ($redirectUrl !== null && $this->userSession->isLoggedIn()) {
$location = $this->urlGenerator->getAbsoluteURL(urldecode($redirectUrl));
// Deny the redirect if the URL contains a @
// This prevents unvalidated redirects like ?redirect_url=:user@domain.com
@@ -275,16 +256,15 @@ class LoginController extends Controller {
* @param string $user
* @param string $password
* @param string $redirect_url
- * @param boolean $remember_login
* @param string $timezone
* @param string $timezone_offset
* @return RedirectResponse
*/
- public function tryLogin($user, $password, $redirect_url, $remember_login = true, $timezone = '', $timezone_offset = '') {
- if(!is_string($user)) {
- throw new \InvalidArgumentException('Username must be string');
- }
-
+ public function tryLogin(string $user,
+ string $password,
+ string $redirect_url = null,
+ string $timezone = '',
+ string $timezone_offset = ''): RedirectResponse {
// If the user is already logged in and the CSRF check does not pass then
// simply redirect the user to the correct page as required. This is the
// case when an user has already logged-in, in another tab.
@@ -292,96 +272,27 @@ class LoginController extends Controller {
return $this->generateRedirect($redirect_url);
}
- if ($this->userManager instanceof PublicEmitter) {
- $this->userManager->emit('\OC\User', 'preLogin', array($user, $password));
- }
-
- $originalUser = $user;
-
- $userObj = $this->userManager->get($user);
-
- if ($userObj !== null && $userObj->isEnabled() === false) {
- $this->logger->warning('Login failed: \''. $user . '\' disabled' .
- ' (Remote IP: \''. $this->request->getRemoteAddress(). '\')',
- ['app' => 'core']);
- return $this->createLoginFailedResponse($user, $originalUser,
- $redirect_url, self::LOGIN_MSG_USERDISABLED);
- }
-
- // TODO: Add all the insane error handling
- /* @var $loginResult IUser */
- $loginResult = $this->userManager->checkPasswordNoLogging($user, $password);
- if ($loginResult === false) {
- $users = $this->userManager->getByEmail($user);
- // we only allow login by email if unique
- if (count($users) === 1) {
- $previousUser = $user;
- $user = $users[0]->getUID();
- if($user !== $previousUser) {
- $loginResult = $this->userManager->checkPassword($user, $password);
- }
- }
- }
-
- if ($loginResult === false) {
- $this->logger->warning('Login failed: \''. $user .
- '\' (Remote IP: \''. $this->request->getRemoteAddress(). '\')',
- ['app' => 'core']);
- return $this->createLoginFailedResponse($user, $originalUser,
- $redirect_url, self::LOGIN_MSG_INVALIDPASSWORD);
- }
-
- // TODO: remove password checks from above and let the user session handle failures
- // requires https://github.com/owncloud/core/pull/24616
- $this->userSession->completeLogin($loginResult, ['loginName' => $user, 'password' => $password]);
-
- $tokenType = IToken::REMEMBER;
- if ((int)$this->config->getSystemValue('remember_login_cookie_lifetime', 60*60*24*15) === 0) {
- $remember_login = false;
- $tokenType = IToken::DO_NOT_REMEMBER;
- }
-
- $this->userSession->createSessionToken($this->request, $loginResult->getUID(), $user, $password, $tokenType);
- $this->userSession->updateTokens($loginResult->getUID(), $password);
-
- // User has successfully logged in, now remove the password reset link, when it is available
- $this->config->deleteUserValue($loginResult->getUID(), 'core', 'lostpassword');
-
- $this->session->set('last-password-confirm', $loginResult->getLastLogin());
-
- if ($timezone_offset !== '') {
- $this->config->setUserValue($loginResult->getUID(), 'core', 'timezone', $timezone);
- $this->session->set('timezone', $timezone_offset);
- }
-
- if ($this->twoFactorManager->isTwoFactorAuthenticated($loginResult)) {
- $this->twoFactorManager->prepareTwoFactorLogin($loginResult, $remember_login);
-
- $providers = $this->twoFactorManager->getProviderSet($loginResult)->getPrimaryProviders();
- if (count($providers) === 1) {
- // Single provider, hence we can redirect to that provider's challenge page directly
- /* @var $provider IProvider */
- $provider = array_pop($providers);
- $url = 'core.TwoFactorChallenge.showChallenge';
- $urlParams = [
- 'challengeProviderId' => $provider->getId(),
- ];
- } else {
- $url = 'core.TwoFactorChallenge.selectChallenge';
- $urlParams = [];
- }
-
- if (!is_null($redirect_url)) {
- $urlParams['redirect_url'] = $redirect_url;
- }
-
- return new RedirectResponse($this->urlGenerator->linkToRoute($url, $urlParams));
+ $data = new LoginData(
+ $this->request,
+ $user,
+ $password,
+ $redirect_url,
+ $timezone,
+ $timezone_offset
+ );
+ $result = $this->loginChain->process($data);
+ if (!$result->isSuccess()) {
+ return $this->createLoginFailedResponse(
+ $data->getUsername(),
+ $user,
+ $redirect_url,
+ $result->getErrorMessage()
+ );
}
- if ($remember_login) {
- $this->userSession->createRememberMeToken($loginResult);
+ if ($result->getRedirectUrl() !== null) {
+ return new RedirectResponse($result->getRedirectUrl());
}
-
return $this->generateRedirect($redirect_url);
}
@@ -398,8 +309,8 @@ class LoginController extends Controller {
$user, $originalUser, $redirect_url, string $loginMessage) {
// Read current user and append if possible we need to
// return the unmodified user otherwise we will leak the login name
- $args = !is_null($user) ? ['user' => $originalUser] : [];
- if (!is_null($redirect_url)) {
+ $args = $user !== null ? ['user' => $originalUser] : [];
+ if ($redirect_url !== null) {
$args['redirect_url'] = $redirect_url;
}
$response = new RedirectResponse(