nextcloud/lib/private/Authentication/LoginCredentials/Store.php
Lionel Elie Mamane f7f053b101 Return correct loginname in credentials,
even when token is invalid or has no password.

Returning the uid as loginname is wrong, and leads to problems when
these differ. E.g. the getapppassword API was creating app token with
the uid as loginname. In a scenario with external authentication (such
as LDAP), these tokens were then invalidated next time their underlying
password was checked, and systematically ceased to function.

Signed-off-by: Lionel Elie Mamane <lionel@mamane.lu>
2020-06-20 11:48:44 +02:00

119 lines
3.6 KiB
PHP

<?php
/**
* @copyright 2016 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@owncloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Authentication\LoginCredentials;
use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
use OC\Authentication\Token\IProvider;
use OCP\Authentication\Exceptions\CredentialsUnavailableException;
use OCP\Authentication\LoginCredentials\ICredentials;
use OCP\Authentication\LoginCredentials\IStore;
use OCP\ILogger;
use OCP\ISession;
use OCP\Session\Exceptions\SessionNotAvailableException;
use OCP\Util;
class Store implements IStore {
/** @var ISession */
private $session;
/** @var ILogger */
private $logger;
/** @var IProvider|null */
private $tokenProvider;
/**
* @param ISession $session
* @param ILogger $logger
* @param IProvider $tokenProvider
*/
public function __construct(ISession $session, ILogger $logger, IProvider $tokenProvider = null) {
$this->session = $session;
$this->logger = $logger;
$this->tokenProvider = $tokenProvider;
Util::connectHook('OC_User', 'post_login', $this, 'authenticate');
}
/**
* Hook listener on post login
*
* @param array $params
*/
public function authenticate(array $params) {
$this->session->set('login_credentials', json_encode($params));
}
/**
* Replace the session implementation
*
* @param ISession $session
*/
public function setSession(ISession $session) {
$this->session = $session;
}
/**
* @since 12
*
* @return ICredentials the login credentials of the current user
* @throws CredentialsUnavailableException
*/
public function getLoginCredentials() {
if (is_null($this->tokenProvider)) {
throw new CredentialsUnavailableException();
}
$trySession = false;
try {
$sessionId = $this->session->getId();
$token = $this->tokenProvider->getToken($sessionId);
$uid = $token->getUID();
$user = $token->getLoginName();
$password = $this->tokenProvider->getPassword($token, $sessionId);
return new Credentials($uid, $user, $password);
} catch (SessionNotAvailableException $ex) {
$this->logger->debug('could not get login credentials because session is unavailable', ['app' => 'core']);
} catch (InvalidTokenException $ex) {
$this->logger->debug('could not get login credentials because the token is invalid', ['app' => 'core']);
$trySession = true;
} catch (PasswordlessTokenException $ex) {
$this->logger->debug('could not get login credentials because the token has no password', ['app' => 'core']);
$trySession = true;
}
if ($trySession && $this->session->exists('login_credentials')) {
$creds = json_decode($this->session->get('login_credentials'));
return new Credentials($creds->uid, $this->session->get('loginname'), $creds->password);
}
// If we reach this line, an exception was thrown.
throw new CredentialsUnavailableException();
}
}