* @author Lukas Reschke * @author Roeland Jago Douma * * @license AGPL-3.0 * * This code is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * 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, version 3, * along with this program. If not, see * */ namespace OCA\Files_External\Lib\Auth\Password; use OCA\Files_External\Lib\Auth\AuthMechanism; use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException; use OCA\Files_External\Lib\StorageConfig; use OCP\Authentication\Exceptions\CredentialsUnavailableException; use OCP\Authentication\LoginCredentials\IStore as CredentialsStore; use OCP\EventDispatcher\IEventDispatcher; use OCP\IL10N; use OCP\ISession; use OCP\IUser; use OCP\Security\ICredentialsManager; use OCP\User\Events\PasswordUpdatedEvent; use OCP\User\Events\UserLoggedInEvent; /** * Username and password from login credentials, saved in DB */ class LoginCredentials extends AuthMechanism { public const CREDENTIALS_IDENTIFIER = 'password::logincredentials/credentials'; /** @var ISession */ protected $session; /** @var ICredentialsManager */ protected $credentialsManager; /** @var CredentialsStore */ private $credentialsStore; public function __construct(IL10N $l, ISession $session, ICredentialsManager $credentialsManager, CredentialsStore $credentialsStore, IEventDispatcher $eventDispatcher) { $this->session = $session; $this->credentialsManager = $credentialsManager; $this->credentialsStore = $credentialsStore; $this ->setIdentifier('password::logincredentials') ->setScheme(self::SCHEME_PASSWORD) ->setText($l->t('Log-in credentials, save in database')) ->addParameters([ ]); $eventDispatcher->addListener(UserLoggedInEvent::class, [$this, 'updateCredentials']); $eventDispatcher->addListener(PasswordUpdatedEvent::class, [$this, 'updateCredentials']); } /** * @param UserLoggedInEvent | PasswordUpdatedEvent $event */ public function updateCredentials($event) { if ($event instanceof UserLoggedInEvent && $event->isTokenLogin()) { return; } $stored = $this->credentialsManager->retrieve($event->getUser()->getUID(), self::CREDENTIALS_IDENTIFIER); if ($stored && $stored['password'] != $event->getPassword()) { $credentials = [ 'user' => $stored['user'], 'password' => $event->getPassword() ]; $this->credentialsManager->store($event->getUser()->getUID(), self::CREDENTIALS_IDENTIFIER, $credentials); } } private function getCredentials(IUser $user): array { $credentials = $this->credentialsManager->retrieve($user->getUID(), self::CREDENTIALS_IDENTIFIER); if (is_null($credentials)) { // nothing saved in db, try to get it from the session and save it try { $sessionCredentials = $this->credentialsStore->getLoginCredentials(); $credentials = [ 'user' => $sessionCredentials->getLoginName(), 'password' => $sessionCredentials->getPassword() ]; $this->credentialsManager->store($user->getUID(), self::CREDENTIALS_IDENTIFIER, $credentials); } catch (CredentialsUnavailableException $e) { throw new InsufficientDataForMeaningfulAnswerException('No login credentials saved'); } } return $credentials; } public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) { if (!isset($user)) { throw new InsufficientDataForMeaningfulAnswerException('No login credentials saved'); } $credentials = $this->getCredentials($user); $storage->setBackendOption('user', $credentials['user']); $storage->setBackendOption('password', $credentials['password']); } }