Session.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. <?php
  2. /**
  3. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  4. * @author Bernhard Posselt <dev@bernhard-posselt.com>
  5. * @author Christoph Wurst <christoph@owncloud.com>
  6. * @author Jörn Friedrich Dreyer <jfd@butonic.de>
  7. * @author Lukas Reschke <lukas@statuscode.ch>
  8. * @author Morris Jobke <hey@morrisjobke.de>
  9. * @author Robin Appelman <icewind@owncloud.com>
  10. * @author Robin McCorkell <robin@mccorkell.me.uk>
  11. * @author Thomas Müller <thomas.mueller@tmit.eu>
  12. * @author Vincent Petry <pvince81@owncloud.com>
  13. *
  14. * @copyright Copyright (c) 2016, ownCloud, Inc.
  15. * @license AGPL-3.0
  16. *
  17. * This code is free software: you can redistribute it and/or modify
  18. * it under the terms of the GNU Affero General Public License, version 3,
  19. * as published by the Free Software Foundation.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU Affero General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU Affero General Public License, version 3,
  27. * along with this program. If not, see <http://www.gnu.org/licenses/>
  28. *
  29. */
  30. namespace OC\User;
  31. use OC;
  32. use OC\Authentication\Exceptions\InvalidTokenException;
  33. use OC\Authentication\Exceptions\PasswordlessTokenException;
  34. use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
  35. use OC\Authentication\Token\IProvider;
  36. use OC\Authentication\Token\IToken;
  37. use OC\Hooks\Emitter;
  38. use OC_User;
  39. use OC_Util;
  40. use OCA\DAV\Connector\Sabre\Auth;
  41. use OCP\AppFramework\Utility\ITimeFactory;
  42. use OCP\IConfig;
  43. use OCP\IRequest;
  44. use OCP\ISession;
  45. use OCP\IUser;
  46. use OCP\IUserManager;
  47. use OCP\IUserSession;
  48. use OCP\Session\Exceptions\SessionNotAvailableException;
  49. use OCP\Util;
  50. /**
  51. * Class Session
  52. *
  53. * Hooks available in scope \OC\User:
  54. * - preSetPassword(\OC\User\User $user, string $password, string $recoverPassword)
  55. * - postSetPassword(\OC\User\User $user, string $password, string $recoverPassword)
  56. * - preDelete(\OC\User\User $user)
  57. * - postDelete(\OC\User\User $user)
  58. * - preCreateUser(string $uid, string $password)
  59. * - postCreateUser(\OC\User\User $user)
  60. * - preLogin(string $user, string $password)
  61. * - postLogin(\OC\User\User $user, string $password)
  62. * - preRememberedLogin(string $uid)
  63. * - postRememberedLogin(\OC\User\User $user)
  64. * - logout()
  65. *
  66. * @package OC\User
  67. */
  68. class Session implements IUserSession, Emitter {
  69. /** @var IUserManager $manager */
  70. private $manager;
  71. /** @var ISession $session */
  72. private $session;
  73. /** @var ITimeFactory */
  74. private $timeFacory;
  75. /** @var IProvider */
  76. private $tokenProvider;
  77. /** @var IConfig */
  78. private $config;
  79. /** @var User $activeUser */
  80. protected $activeUser;
  81. /**
  82. * @param IUserManager $manager
  83. * @param ISession $session
  84. * @param ITimeFactory $timeFacory
  85. * @param IProvider $tokenProvider
  86. * @param IConfig $config
  87. */
  88. public function __construct(IUserManager $manager, ISession $session, ITimeFactory $timeFacory, $tokenProvider, IConfig $config) {
  89. $this->manager = $manager;
  90. $this->session = $session;
  91. $this->timeFacory = $timeFacory;
  92. $this->tokenProvider = $tokenProvider;
  93. $this->config = $config;
  94. }
  95. /**
  96. * @param IProvider $provider
  97. */
  98. public function setTokenProvider(IProvider $provider) {
  99. $this->tokenProvider = $provider;
  100. }
  101. /**
  102. * @param string $scope
  103. * @param string $method
  104. * @param callable $callback
  105. */
  106. public function listen($scope, $method, callable $callback) {
  107. $this->manager->listen($scope, $method, $callback);
  108. }
  109. /**
  110. * @param string $scope optional
  111. * @param string $method optional
  112. * @param callable $callback optional
  113. */
  114. public function removeListener($scope = null, $method = null, callable $callback = null) {
  115. $this->manager->removeListener($scope, $method, $callback);
  116. }
  117. /**
  118. * get the manager object
  119. *
  120. * @return Manager
  121. */
  122. public function getManager() {
  123. return $this->manager;
  124. }
  125. /**
  126. * get the session object
  127. *
  128. * @return ISession
  129. */
  130. public function getSession() {
  131. return $this->session;
  132. }
  133. /**
  134. * set the session object
  135. *
  136. * @param ISession $session
  137. */
  138. public function setSession(ISession $session) {
  139. if ($this->session instanceof ISession) {
  140. $this->session->close();
  141. }
  142. $this->session = $session;
  143. $this->activeUser = null;
  144. }
  145. /**
  146. * set the currently active user
  147. *
  148. * @param User|null $user
  149. */
  150. public function setUser($user) {
  151. if (is_null($user)) {
  152. $this->session->remove('user_id');
  153. } else {
  154. $this->session->set('user_id', $user->getUID());
  155. }
  156. $this->activeUser = $user;
  157. }
  158. /**
  159. * get the current active user
  160. *
  161. * @return IUser|null Current user, otherwise null
  162. */
  163. public function getUser() {
  164. // FIXME: This is a quick'n dirty work-around for the incognito mode as
  165. // described at https://github.com/owncloud/core/pull/12912#issuecomment-67391155
  166. if (OC_User::isIncognitoMode()) {
  167. return null;
  168. }
  169. if (is_null($this->activeUser)) {
  170. $uid = $this->session->get('user_id');
  171. if (is_null($uid)) {
  172. return null;
  173. }
  174. $this->activeUser = $this->manager->get($uid);
  175. if (is_null($this->activeUser)) {
  176. return null;
  177. }
  178. $this->validateSession();
  179. }
  180. return $this->activeUser;
  181. }
  182. /**
  183. * Validate whether the current session is valid
  184. *
  185. * - For token-authenticated clients, the token validity is checked
  186. * - For browsers, the session token validity is checked
  187. */
  188. protected function validateSession() {
  189. $token = null;
  190. $appPassword = $this->session->get('app_password');
  191. if (is_null($appPassword)) {
  192. try {
  193. $token = $this->session->getId();
  194. } catch (SessionNotAvailableException $ex) {
  195. return;
  196. }
  197. } else {
  198. $token = $appPassword;
  199. }
  200. if (!$this->validateToken($token)) {
  201. // Session was invalidated
  202. $this->logout();
  203. }
  204. }
  205. /**
  206. * Checks whether the user is logged in
  207. *
  208. * @return bool if logged in
  209. */
  210. public function isLoggedIn() {
  211. $user = $this->getUser();
  212. if (is_null($user)) {
  213. return false;
  214. }
  215. return $user->isEnabled();
  216. }
  217. /**
  218. * set the login name
  219. *
  220. * @param string|null $loginName for the logged in user
  221. */
  222. public function setLoginName($loginName) {
  223. if (is_null($loginName)) {
  224. $this->session->remove('loginname');
  225. } else {
  226. $this->session->set('loginname', $loginName);
  227. }
  228. }
  229. /**
  230. * get the login name of the current user
  231. *
  232. * @return string
  233. */
  234. public function getLoginName() {
  235. if ($this->activeUser) {
  236. return $this->session->get('loginname');
  237. } else {
  238. $uid = $this->session->get('user_id');
  239. if ($uid) {
  240. $this->activeUser = $this->manager->get($uid);
  241. return $this->session->get('loginname');
  242. } else {
  243. return null;
  244. }
  245. }
  246. }
  247. /**
  248. * try to log in with the provided credentials
  249. *
  250. * @param string $uid
  251. * @param string $password
  252. * @return boolean|null
  253. * @throws LoginException
  254. */
  255. public function login($uid, $password) {
  256. $this->session->regenerateId();
  257. if ($this->validateToken($password)) {
  258. // When logging in with token, the password must be decrypted first before passing to login hook
  259. try {
  260. $token = $this->tokenProvider->getToken($password);
  261. try {
  262. $loginPassword = $this->tokenProvider->getPassword($token, $password);
  263. $this->manager->emit('\OC\User', 'preLogin', array($uid, $loginPassword));
  264. } catch (PasswordlessTokenException $ex) {
  265. $this->manager->emit('\OC\User', 'preLogin', array($uid, ''));
  266. }
  267. } catch (InvalidTokenException $ex) {
  268. // Invalid token, nothing to do
  269. }
  270. $this->loginWithToken($password);
  271. $user = $this->getUser();
  272. } else {
  273. $this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
  274. $user = $this->manager->checkPassword($uid, $password);
  275. }
  276. if ($user !== false) {
  277. if (!is_null($user)) {
  278. if ($user->isEnabled()) {
  279. $this->setUser($user);
  280. $this->setLoginName($uid);
  281. $this->manager->emit('\OC\User', 'postLogin', array($user, $password));
  282. if ($this->isLoggedIn()) {
  283. $this->prepareUserLogin();
  284. return true;
  285. } else {
  286. // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory
  287. $message = \OC::$server->getL10N('lib')->t('Login canceled by app');
  288. throw new LoginException($message);
  289. }
  290. } else {
  291. // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory
  292. $message = \OC::$server->getL10N('lib')->t('User disabled');
  293. throw new LoginException($message);
  294. }
  295. }
  296. }
  297. return false;
  298. }
  299. /**
  300. * Tries to log in a client
  301. *
  302. * Checks token auth enforced
  303. * Checks 2FA enabled
  304. *
  305. * @param string $user
  306. * @param string $password
  307. * @param IRequest $request
  308. * @throws LoginException
  309. * @throws PasswordLoginForbiddenException
  310. * @return boolean
  311. */
  312. public function logClientIn($user, $password, IRequest $request) {
  313. $isTokenPassword = $this->isTokenPassword($password);
  314. if (!$isTokenPassword && $this->isTokenAuthEnforced()) {
  315. throw new PasswordLoginForbiddenException();
  316. }
  317. if (!$isTokenPassword && $this->isTwoFactorEnforced($user)) {
  318. throw new PasswordLoginForbiddenException();
  319. }
  320. if (!$this->login($user, $password) ) {
  321. $users = $this->manager->getByEmail($user);
  322. if (count($users) === 1) {
  323. return $this->login($users[0]->getUID(), $password);
  324. }
  325. return false;
  326. }
  327. if ($isTokenPassword) {
  328. $this->session->set('app_password', $password);
  329. } else if($this->supportsCookies($request)) {
  330. // Password login, but cookies supported -> create (browser) session token
  331. $this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
  332. }
  333. return true;
  334. }
  335. protected function supportsCookies(IRequest $request) {
  336. if (!is_null($request->getCookie('cookie_test'))) {
  337. return true;
  338. }
  339. setcookie('cookie_test', 'test', $this->timeFacory->getTime() + 3600);
  340. return false;
  341. }
  342. private function isTokenAuthEnforced() {
  343. return $this->config->getSystemValue('token_auth_enforced', false);
  344. }
  345. protected function isTwoFactorEnforced($username) {
  346. Util::emitHook(
  347. '\OCA\Files_Sharing\API\Server2Server',
  348. 'preLoginNameUsedAsUserName',
  349. array('uid' => &$username)
  350. );
  351. $user = $this->manager->get($username);
  352. if (is_null($user)) {
  353. $users = $this->manager->getByEmail($username);
  354. if (count($users) !== 1) {
  355. return true;
  356. }
  357. $user = $users[0];
  358. }
  359. // DI not possible due to cyclic dependencies :'-/
  360. return OC::$server->getTwoFactorAuthManager()->isTwoFactorAuthenticated($user);
  361. }
  362. /**
  363. * Check if the given 'password' is actually a device token
  364. *
  365. * @param string $password
  366. * @return boolean
  367. */
  368. public function isTokenPassword($password) {
  369. try {
  370. $this->tokenProvider->getToken($password);
  371. return true;
  372. } catch (InvalidTokenException $ex) {
  373. return false;
  374. }
  375. }
  376. protected function prepareUserLogin() {
  377. // TODO: mock/inject/use non-static
  378. // Refresh the token
  379. \OC::$server->getCsrfTokenManager()->refreshToken();
  380. //we need to pass the user name, which may differ from login name
  381. $user = $this->getUser()->getUID();
  382. OC_Util::setupFS($user);
  383. //trigger creation of user home and /files folder
  384. \OC::$server->getUserFolder($user);
  385. }
  386. /**
  387. * Tries to login the user with HTTP Basic Authentication
  388. *
  389. * @todo do not allow basic auth if the user is 2FA enforced
  390. * @param IRequest $request
  391. * @return boolean if the login was successful
  392. */
  393. public function tryBasicAuthLogin(IRequest $request) {
  394. if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) {
  395. try {
  396. if ($this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request)) {
  397. /**
  398. * Add DAV authenticated. This should in an ideal world not be
  399. * necessary but the iOS App reads cookies from anywhere instead
  400. * only the DAV endpoint.
  401. * This makes sure that the cookies will be valid for the whole scope
  402. * @see https://github.com/owncloud/core/issues/22893
  403. */
  404. $this->session->set(
  405. Auth::DAV_AUTHENTICATED, $this->getUser()->getUID()
  406. );
  407. return true;
  408. }
  409. } catch (PasswordLoginForbiddenException $ex) {
  410. // Nothing to do
  411. }
  412. }
  413. return false;
  414. }
  415. private function loginWithToken($token) {
  416. try {
  417. $dbToken = $this->tokenProvider->getToken($token);
  418. } catch (InvalidTokenException $ex) {
  419. return false;
  420. }
  421. $uid = $dbToken->getUID();
  422. $password = '';
  423. try {
  424. $password = $this->tokenProvider->getPassword($dbToken, $token);
  425. } catch (PasswordlessTokenException $ex) {
  426. // Ignore and use empty string instead
  427. }
  428. $this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
  429. $user = $this->manager->get($uid);
  430. if (is_null($user)) {
  431. // user does not exist
  432. return false;
  433. }
  434. if (!$user->isEnabled()) {
  435. // disabled users can not log in
  436. return false;
  437. }
  438. //login
  439. $this->setUser($user);
  440. $this->manager->emit('\OC\User', 'postLogin', array($user, $password));
  441. return true;
  442. }
  443. /**
  444. * Create a new session token for the given user credentials
  445. *
  446. * @param IRequest $request
  447. * @param string $uid user UID
  448. * @param string $loginName login name
  449. * @param string $password
  450. * @return boolean
  451. */
  452. public function createSessionToken(IRequest $request, $uid, $loginName, $password = null) {
  453. if (is_null($this->manager->get($uid))) {
  454. // User does not exist
  455. return false;
  456. }
  457. $name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser';
  458. try {
  459. $sessionId = $this->session->getId();
  460. $pwd = $this->getPassword($password);
  461. $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name);
  462. return true;
  463. } catch (SessionNotAvailableException $ex) {
  464. // This can happen with OCC, where a memory session is used
  465. // if a memory session is used, we shouldn't create a session token anyway
  466. return false;
  467. }
  468. }
  469. /**
  470. * Checks if the given password is a token.
  471. * If yes, the password is extracted from the token.
  472. * If no, the same password is returned.
  473. *
  474. * @param string $password either the login password or a device token
  475. * @return string|null the password or null if none was set in the token
  476. */
  477. private function getPassword($password) {
  478. if (is_null($password)) {
  479. // This is surely no token ;-)
  480. return null;
  481. }
  482. try {
  483. $token = $this->tokenProvider->getToken($password);
  484. try {
  485. return $this->tokenProvider->getPassword($token, $password);
  486. } catch (PasswordlessTokenException $ex) {
  487. return null;
  488. }
  489. } catch (InvalidTokenException $ex) {
  490. return $password;
  491. }
  492. }
  493. /**
  494. * @param IToken $dbToken
  495. * @param string $token
  496. * @return boolean
  497. */
  498. private function checkTokenCredentials(IToken $dbToken, $token) {
  499. // Check whether login credentials are still valid and the user was not disabled
  500. // This check is performed each 5 minutes
  501. $lastCheck = $dbToken->getLastCheck() ? : 0;
  502. $now = $this->timeFacory->getTime();
  503. if ($lastCheck > ($now - 60 * 5)) {
  504. // Checked performed recently, nothing to do now
  505. return true;
  506. }
  507. try {
  508. $pwd = $this->tokenProvider->getPassword($dbToken, $token);
  509. } catch (InvalidTokenException $ex) {
  510. // An invalid token password was used -> log user out
  511. return false;
  512. } catch (PasswordlessTokenException $ex) {
  513. // Token has no password
  514. if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) {
  515. $this->tokenProvider->invalidateToken($token);
  516. return false;
  517. }
  518. $dbToken->setLastCheck($now);
  519. $this->tokenProvider->updateToken($dbToken);
  520. return true;
  521. }
  522. if ($this->manager->checkPassword($dbToken->getLoginName(), $pwd) === false
  523. || (!is_null($this->activeUser) && !$this->activeUser->isEnabled())) {
  524. $this->tokenProvider->invalidateToken($token);
  525. // Password has changed or user was disabled -> log user out
  526. return false;
  527. }
  528. $dbToken->setLastCheck($now);
  529. $this->tokenProvider->updateToken($dbToken);
  530. return true;
  531. }
  532. /**
  533. * Check if the given token exists and performs password/user-enabled checks
  534. *
  535. * Invalidates the token if checks fail
  536. *
  537. * @param string $token
  538. * @return boolean
  539. */
  540. private function validateToken($token) {
  541. try {
  542. $dbToken = $this->tokenProvider->getToken($token);
  543. } catch (InvalidTokenException $ex) {
  544. return false;
  545. }
  546. if (!$this->checkTokenCredentials($dbToken, $token)) {
  547. return false;
  548. }
  549. $this->tokenProvider->updateTokenActivity($dbToken);
  550. return true;
  551. }
  552. /**
  553. * Tries to login the user with auth token header
  554. *
  555. * @todo check remember me cookie
  556. * @return boolean
  557. */
  558. public function tryTokenLogin(IRequest $request) {
  559. $authHeader = $request->getHeader('Authorization');
  560. if (strpos($authHeader, 'token ') === false) {
  561. // No auth header, let's try session id
  562. try {
  563. $token = $this->session->getId();
  564. } catch (SessionNotAvailableException $ex) {
  565. return false;
  566. }
  567. } else {
  568. $token = substr($authHeader, 6);
  569. }
  570. if (!$this->loginWithToken($token)) {
  571. return false;
  572. }
  573. if(!$this->validateToken($token)) {
  574. return false;
  575. }
  576. return true;
  577. }
  578. /**
  579. * perform login using the magic cookie (remember login)
  580. *
  581. * @param string $uid the username
  582. * @param string $currentToken
  583. * @return bool
  584. */
  585. public function loginWithCookie($uid, $currentToken) {
  586. $this->session->regenerateId();
  587. $this->manager->emit('\OC\User', 'preRememberedLogin', array($uid));
  588. $user = $this->manager->get($uid);
  589. if (is_null($user)) {
  590. // user does not exist
  591. return false;
  592. }
  593. // get stored tokens
  594. $tokens = OC::$server->getConfig()->getUserKeys($uid, 'login_token');
  595. // test cookies token against stored tokens
  596. if (!in_array($currentToken, $tokens, true)) {
  597. return false;
  598. }
  599. // replace successfully used token with a new one
  600. OC::$server->getConfig()->deleteUserValue($uid, 'login_token', $currentToken);
  601. $newToken = OC::$server->getSecureRandom()->generate(32);
  602. OC::$server->getConfig()->setUserValue($uid, 'login_token', $newToken, time());
  603. $this->setMagicInCookie($user->getUID(), $newToken);
  604. //login
  605. $this->setUser($user);
  606. $this->manager->emit('\OC\User', 'postRememberedLogin', array($user));
  607. return true;
  608. }
  609. /**
  610. * logout the user from the session
  611. */
  612. public function logout() {
  613. $this->manager->emit('\OC\User', 'logout');
  614. $user = $this->getUser();
  615. if (!is_null($user)) {
  616. try {
  617. $this->tokenProvider->invalidateToken($this->session->getId());
  618. } catch (SessionNotAvailableException $ex) {
  619. }
  620. }
  621. $this->setUser(null);
  622. $this->setLoginName(null);
  623. $this->unsetMagicInCookie();
  624. $this->session->clear();
  625. }
  626. /**
  627. * Set cookie value to use in next page load
  628. *
  629. * @param string $username username to be set
  630. * @param string $token
  631. */
  632. public function setMagicInCookie($username, $token) {
  633. $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
  634. $expires = time() + OC::$server->getConfig()->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
  635. setcookie('oc_username', $username, $expires, OC::$WEBROOT, '', $secureCookie, true);
  636. setcookie('oc_token', $token, $expires, OC::$WEBROOT, '', $secureCookie, true);
  637. setcookie('oc_remember_login', '1', $expires, OC::$WEBROOT, '', $secureCookie, true);
  638. }
  639. /**
  640. * Remove cookie for "remember username"
  641. */
  642. public function unsetMagicInCookie() {
  643. //TODO: DI for cookies and IRequest
  644. $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
  645. unset($_COOKIE['oc_username']); //TODO: DI
  646. unset($_COOKIE['oc_token']);
  647. unset($_COOKIE['oc_remember_login']);
  648. setcookie('oc_username', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
  649. setcookie('oc_token', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
  650. setcookie('oc_remember_login', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
  651. // old cookies might be stored under /webroot/ instead of /webroot
  652. // and Firefox doesn't like it!
  653. setcookie('oc_username', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
  654. setcookie('oc_token', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
  655. setcookie('oc_remember_login', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
  656. }
  657. /**
  658. * Update password of the browser session token if there is one
  659. *
  660. * @param string $password
  661. */
  662. public function updateSessionTokenPassword($password) {
  663. try {
  664. $sessionId = $this->session->getId();
  665. $token = $this->tokenProvider->getToken($sessionId);
  666. $this->tokenProvider->setPassword($token, $sessionId, $password);
  667. } catch (SessionNotAvailableException $ex) {
  668. // Nothing to do
  669. } catch (InvalidTokenException $ex) {
  670. // Nothing to do
  671. }
  672. }
  673. }