bring back remember-me
* try to reuse the old session token for remember me login * decrypt/encrypt token password and set the session id accordingly * create remember-me cookies only if checkbox is checked and 2fa solved * adjust db token cleanup to store remembered tokens longer * adjust unit tests Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
parent
dada3ffb51
commit
d907666232
|
@ -196,9 +196,10 @@ class LoginController extends Controller {
|
|||
* @param string $user
|
||||
* @param string $password
|
||||
* @param string $redirect_url
|
||||
* @param boolean $remember_login
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function tryLogin($user, $password, $redirect_url) {
|
||||
public function tryLogin($user, $password, $redirect_url, $remember_login = false) {
|
||||
$currentDelay = $this->throttler->getDelay($this->request->getRemoteAddress());
|
||||
$this->throttler->sleepDelay($this->request->getRemoteAddress());
|
||||
|
||||
|
@ -236,13 +237,13 @@ class LoginController extends Controller {
|
|||
// TODO: remove password checks from above and let the user session handle failures
|
||||
// requires https://github.com/owncloud/core/pull/24616
|
||||
$this->userSession->login($user, $password);
|
||||
$this->userSession->createSessionToken($this->request, $loginResult->getUID(), $user, $password);
|
||||
$this->userSession->createSessionToken($this->request, $loginResult->getUID(), $user, $password, $remember_login);
|
||||
|
||||
// User has successfully logged in, now remove the password reset link, when it is available
|
||||
$this->config->deleteUserValue($loginResult->getUID(), 'core', 'lostpassword');
|
||||
|
||||
if ($this->twoFactorManager->isTwoFactorAuthenticated($loginResult)) {
|
||||
$this->twoFactorManager->prepareTwoFactorLogin($loginResult);
|
||||
$this->twoFactorManager->prepareTwoFactorLogin($loginResult, $remember_login);
|
||||
|
||||
$providers = $this->twoFactorManager->getProviders($loginResult);
|
||||
if (count($providers) === 1) {
|
||||
|
@ -265,6 +266,10 @@ class LoginController extends Controller {
|
|||
return new RedirectResponse($this->urlGenerator->linkToRoute($url, $urlParams));
|
||||
}
|
||||
|
||||
if ($remember_login) {
|
||||
$this->userSession->createRememberMeToken($loginResult);
|
||||
}
|
||||
|
||||
return $this->generateRedirect($redirect_url);
|
||||
}
|
||||
|
||||
|
|
|
@ -1125,6 +1125,15 @@
|
|||
<length>2</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>remember</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<unsigned>true</unsigned>
|
||||
<length>1</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>last_activity</name>
|
||||
<type>integer</type>
|
||||
|
|
|
@ -1035,6 +1035,12 @@ class OC {
|
|||
if ($userSession->tryTokenLogin($request)) {
|
||||
return true;
|
||||
}
|
||||
if (isset($_COOKIE['nc_username'])
|
||||
&& isset($_COOKIE['nc_token'])
|
||||
&& isset($_COOKIE['nc_session_id'])
|
||||
&& $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
|
||||
return true;
|
||||
}
|
||||
if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -290,6 +290,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
|
|||
$this->registerService('OCP\\IUserSession', function($c) {
|
||||
return $this->getServer()->getUserSession();
|
||||
});
|
||||
$this->registerAlias(\OC\User\Session::class, \OCP\IUserSession::class);
|
||||
|
||||
$this->registerService('OCP\\ISession', function($c) {
|
||||
return $this->getServer()->getSession();
|
||||
|
|
|
@ -35,6 +35,8 @@ use OCP\AppFramework\Db\Entity;
|
|||
* @method string getToken()
|
||||
* @method void setType(string $type)
|
||||
* @method int getType()
|
||||
* @method void setRemember(int $remember)
|
||||
* @method int getRemember()
|
||||
* @method void setLastActivity(int $lastActivity)
|
||||
* @method int getLastActivity()
|
||||
*/
|
||||
|
@ -70,6 +72,11 @@ class DefaultToken extends Entity implements IToken {
|
|||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $remember;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
|
|
@ -40,24 +40,25 @@ class DefaultTokenMapper extends Mapper {
|
|||
* @param string $token
|
||||
*/
|
||||
public function invalidate($token) {
|
||||
/* @var $qb IQueryBuilder */
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('authtoken')
|
||||
->andWhere($qb->expr()->eq('token', $qb->createParameter('token')))
|
||||
->where($qb->expr()->eq('token', $qb->createParameter('token')))
|
||||
->setParameter('token', $token)
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $olderThan
|
||||
* @param int $remember
|
||||
*/
|
||||
public function invalidateOld($olderThan) {
|
||||
public function invalidateOld($olderThan, $remember = IToken::DO_NOT_REMEMBER) {
|
||||
/* @var $qb IQueryBuilder */
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('authtoken')
|
||||
->where($qb->expr()->lt('last_activity', $qb->createParameter('last_activity')))
|
||||
->andWhere($qb->expr()->eq('type', $qb->createParameter('type')))
|
||||
->setParameter('last_activity', $olderThan, IQueryBuilder::PARAM_INT)
|
||||
->setParameter('type', IToken::TEMPORARY_TOKEN, IQueryBuilder::PARAM_INT)
|
||||
->where($qb->expr()->lt('last_activity', $qb->createNamedParameter($olderThan, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('type', $qb->createNamedParameter(IToken::TEMPORARY_TOKEN, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('remember', $qb->createNamedParameter($remember, IQueryBuilder::PARAM_INT)))
|
||||
->execute();
|
||||
}
|
||||
|
||||
|
@ -71,7 +72,7 @@ class DefaultTokenMapper extends Mapper {
|
|||
public function getToken($token) {
|
||||
/* @var $qb IQueryBuilder */
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check')
|
||||
$result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check')
|
||||
->from('authtoken')
|
||||
->where($qb->expr()->eq('token', $qb->createParameter('token')))
|
||||
->setParameter('token', $token)
|
||||
|
@ -97,7 +98,7 @@ class DefaultTokenMapper extends Mapper {
|
|||
public function getTokenByUser(IUser $user) {
|
||||
/* @var $qb IQueryBuilder */
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check')
|
||||
$qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check')
|
||||
->from('authtoken')
|
||||
->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())))
|
||||
->setMaxResults(1000);
|
||||
|
|
|
@ -73,9 +73,10 @@ class DefaultTokenProvider implements IProvider {
|
|||
* @param string|null $password
|
||||
* @param string $name
|
||||
* @param int $type token type
|
||||
* @param int $remember whether the session token should be used for remember-me
|
||||
* @return IToken
|
||||
*/
|
||||
public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN) {
|
||||
public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN, $remember = IToken::DO_NOT_REMEMBER) {
|
||||
$dbToken = new DefaultToken();
|
||||
$dbToken->setUid($uid);
|
||||
$dbToken->setLoginName($loginName);
|
||||
|
@ -85,6 +86,7 @@ class DefaultTokenProvider implements IProvider {
|
|||
$dbToken->setName($name);
|
||||
$dbToken->setToken($this->hashToken($token));
|
||||
$dbToken->setType($type);
|
||||
$dbToken->setRemember($remember);
|
||||
$dbToken->setLastActivity($this->time->getTime());
|
||||
|
||||
$this->mapper->insert($dbToken);
|
||||
|
@ -151,6 +153,27 @@ class DefaultTokenProvider implements IProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $oldSessionId
|
||||
* @param string $sessionId
|
||||
*/
|
||||
public function renewSessionToken($oldSessionId, $sessionId) {
|
||||
$token = $this->getToken($oldSessionId);
|
||||
|
||||
$newToken = new DefaultToken();
|
||||
$newToken->setUid($token->getUID());
|
||||
$newToken->setLoginName($token->getLoginName());
|
||||
if (!is_null($token->getPassword())) {
|
||||
$password = $this->decryptPassword($token->getPassword(), $oldSessionId);
|
||||
$newToken->setPassword($this->encryptPassword($password, $sessionId));
|
||||
}
|
||||
$newToken->setName($token->getName());
|
||||
$newToken->setToken($this->hashToken($sessionId));
|
||||
$newToken->setType(IToken::TEMPORARY_TOKEN);
|
||||
$newToken->setLastActivity($this->time->getTime());
|
||||
$this->mapper->insert($newToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IToken $savedToken
|
||||
* @param string $tokenId session token
|
||||
|
@ -207,8 +230,11 @@ class DefaultTokenProvider implements IProvider {
|
|||
*/
|
||||
public function invalidateOldTokens() {
|
||||
$olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24);
|
||||
$this->logger->info('Invalidating tokens older than ' . date('c', $olderThan));
|
||||
$this->mapper->invalidateOld($olderThan);
|
||||
$this->logger->info('Invalidating session tokens older than ' . date('c', $olderThan));
|
||||
$this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER);
|
||||
$rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
|
||||
$this->logger->info('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold));
|
||||
$this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,7 @@ use OCP\IUser;
|
|||
|
||||
interface IProvider {
|
||||
|
||||
|
||||
/**
|
||||
* Create and persist a new token
|
||||
*
|
||||
|
@ -37,9 +38,10 @@ interface IProvider {
|
|||
* @param string|null $password
|
||||
* @param string $name
|
||||
* @param int $type token type
|
||||
* @param int $remember whether the session token should be used for remember-me
|
||||
* @return IToken
|
||||
*/
|
||||
public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN);
|
||||
public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN, $remember = IToken::DO_NOT_REMEMBER);
|
||||
|
||||
/**
|
||||
* Get a token by token id
|
||||
|
@ -50,6 +52,12 @@ interface IProvider {
|
|||
*/
|
||||
public function getToken($tokenId) ;
|
||||
|
||||
/**
|
||||
* @param string $oldSessionId
|
||||
* @param string $sessionId
|
||||
*/
|
||||
public function renewSessionToken($oldSessionId, $sessionId);
|
||||
|
||||
/**
|
||||
* Invalidate (delete) the given session token
|
||||
*
|
||||
|
|
|
@ -28,6 +28,8 @@ interface IToken extends JsonSerializable {
|
|||
|
||||
const TEMPORARY_TOKEN = 0;
|
||||
const PERMANENT_TOKEN = 1;
|
||||
const DO_NOT_REMEMBER = 0;
|
||||
const REMEMBER = 1;
|
||||
|
||||
/**
|
||||
* Get the token ID
|
||||
|
|
|
@ -37,6 +37,7 @@ class Manager {
|
|||
const SESSION_UID_KEY = 'two_factor_auth_uid';
|
||||
const BACKUP_CODES_APP_ID = 'twofactor_backupcodes';
|
||||
const BACKUP_CODES_PROVIDER_ID = 'backup_codes';
|
||||
const REMEBER_LOGIN = 'two_factor_remember_login';
|
||||
|
||||
/** @var AppManager */
|
||||
private $appManager;
|
||||
|
@ -51,6 +52,7 @@ class Manager {
|
|||
* @param AppManager $appManager
|
||||
* @param ISession $session
|
||||
* @param IConfig $config
|
||||
* @param Session $userSession
|
||||
*/
|
||||
public function __construct(AppManager $appManager, ISession $session, IConfig $config) {
|
||||
$this->appManager = $appManager;
|
||||
|
@ -171,11 +173,16 @@ class Manager {
|
|||
return false;
|
||||
}
|
||||
|
||||
$result = $provider->verifyChallenge($user, $challenge);
|
||||
if ($result) {
|
||||
$this->session->remove(self::SESSION_UID_KEY);
|
||||
$passed = $provider->verifyChallenge($user, $challenge);
|
||||
if ($passed) {
|
||||
if ($this->session->get(self::REMEBER_LOGIN) === true) {
|
||||
// TODO: resolve cyclic dependency and use DI
|
||||
\OC::$server->getUserSession()->createRememberMeToken($user);
|
||||
}
|
||||
return $result;
|
||||
$this->session->remove(self::SESSION_UID_KEY);
|
||||
$this->session->remove(self::REMEBER_LOGIN);
|
||||
}
|
||||
return $passed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -202,12 +209,14 @@ class Manager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Prepare the 2FA login (set session value)
|
||||
* Prepare the 2FA login
|
||||
*
|
||||
* @param IUser $user
|
||||
* @param boolean $rememberMe
|
||||
*/
|
||||
public function prepareTwoFactorLogin(IUser $user) {
|
||||
public function prepareTwoFactorLogin(IUser $user, $rememberMe) {
|
||||
$this->session->set(self::SESSION_UID_KEY, $user->getUID());
|
||||
$this->session->set(self::REMEBER_LOGIN, $rememberMe);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
return $userSession;
|
||||
});
|
||||
|
||||
$this->registerService('\OC\Authentication\TwoFactorAuth\Manager', function (Server $c) {
|
||||
$this->registerService(\OC\Authentication\TwoFactorAuth\Manager::class, function (Server $c) {
|
||||
return new \OC\Authentication\TwoFactorAuth\Manager($c->getAppManager(), $c->getSession(), $c->getConfig());
|
||||
});
|
||||
|
||||
|
|
|
@ -526,9 +526,10 @@ class Session implements IUserSession, Emitter {
|
|||
* @param string $uid user UID
|
||||
* @param string $loginName login name
|
||||
* @param string $password
|
||||
* @param int $remember
|
||||
* @return boolean
|
||||
*/
|
||||
public function createSessionToken(IRequest $request, $uid, $loginName, $password = null) {
|
||||
public function createSessionToken(IRequest $request, $uid, $loginName, $password = null, $remember = IToken::DO_NOT_REMEMBER) {
|
||||
if (is_null($this->manager->get($uid))) {
|
||||
// User does not exist
|
||||
return false;
|
||||
|
@ -537,7 +538,7 @@ class Session implements IUserSession, Emitter {
|
|||
try {
|
||||
$sessionId = $this->session->getId();
|
||||
$pwd = $this->getPassword($password);
|
||||
$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name);
|
||||
$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, IToken::REMEMBER);
|
||||
return true;
|
||||
} catch (SessionNotAvailableException $ex) {
|
||||
// This can happen with OCC, where a memory session is used
|
||||
|
@ -680,9 +681,10 @@ class Session implements IUserSession, Emitter {
|
|||
*
|
||||
* @param string $uid the username
|
||||
* @param string $currentToken
|
||||
* @param string $oldSessionId
|
||||
* @return bool
|
||||
*/
|
||||
public function loginWithCookie($uid, $currentToken) {
|
||||
public function loginWithCookie($uid, $currentToken, $oldSessionId) {
|
||||
$this->session->regenerateId();
|
||||
$this->manager->emit('\OC\User', 'preRememberedLogin', array($uid));
|
||||
$user = $this->manager->get($uid);
|
||||
|
@ -692,15 +694,26 @@ class Session implements IUserSession, Emitter {
|
|||
}
|
||||
|
||||
// get stored tokens
|
||||
$tokens = OC::$server->getConfig()->getUserKeys($uid, 'login_token');
|
||||
$tokens = $this->config->getUserKeys($uid, 'login_token');
|
||||
// test cookies token against stored tokens
|
||||
if (!in_array($currentToken, $tokens, true)) {
|
||||
return false;
|
||||
}
|
||||
// replace successfully used token with a new one
|
||||
OC::$server->getConfig()->deleteUserValue($uid, 'login_token', $currentToken);
|
||||
$this->config->deleteUserValue($uid, 'login_token', $currentToken);
|
||||
$newToken = OC::$server->getSecureRandom()->generate(32);
|
||||
OC::$server->getConfig()->setUserValue($uid, 'login_token', $newToken, time());
|
||||
$this->config->setUserValue($uid, 'login_token', $newToken, $this->timeFacory->getTime());
|
||||
|
||||
try {
|
||||
$sessionId = $this->session->getId();
|
||||
$this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
|
||||
} catch (SessionNotAvailableException $ex) {
|
||||
return false;
|
||||
} catch (InvalidTokenException $ex) {
|
||||
\OC::$server->getLogger()->warning('Renewing session token failed', ['app' => 'core']);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setMagicInCookie($user->getUID(), $newToken);
|
||||
|
||||
//login
|
||||
|
@ -709,6 +722,15 @@ class Session implements IUserSession, Emitter {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
*/
|
||||
public function createRememberMeToken(IUser $user) {
|
||||
$token = OC::$server->getSecureRandom()->generate(32);
|
||||
$this->config->setUserValue($user->getUID(), 'login_token', $token, time());
|
||||
$this->setMagicInCookie($user->getUID(), $token);
|
||||
}
|
||||
|
||||
/**
|
||||
* logout the user from the session
|
||||
*/
|
||||
|
@ -736,10 +758,19 @@ class Session implements IUserSession, Emitter {
|
|||
*/
|
||||
public function setMagicInCookie($username, $token) {
|
||||
$secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
|
||||
$expires = time() + OC::$server->getConfig()->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
|
||||
setcookie('oc_username', $username, $expires, OC::$WEBROOT, '', $secureCookie, true);
|
||||
setcookie('oc_token', $token, $expires, OC::$WEBROOT, '', $secureCookie, true);
|
||||
setcookie('oc_remember_login', '1', $expires, OC::$WEBROOT, '', $secureCookie, true);
|
||||
$webRoot = \OC::$WEBROOT;
|
||||
if ($webRoot === '') {
|
||||
$webRoot = '/';
|
||||
}
|
||||
|
||||
$expires = $this->timeFacory->getTime() + OC::$server->getConfig()->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
|
||||
setcookie('nc_username', $username, $expires, $webRoot, '', $secureCookie, true);
|
||||
setcookie('nc_token', $token, $expires, $webRoot, '', $secureCookie, true);
|
||||
try {
|
||||
setcookie('nc_session_id', $this->session->getId(), $expires, $webRoot, '', $secureCookie, true);
|
||||
} catch (SessionNotAvailableException $ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -749,17 +780,17 @@ class Session implements IUserSession, Emitter {
|
|||
//TODO: DI for cookies and IRequest
|
||||
$secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
|
||||
|
||||
unset($_COOKIE['oc_username']); //TODO: DI
|
||||
unset($_COOKIE['oc_token']);
|
||||
unset($_COOKIE['oc_remember_login']);
|
||||
setcookie('oc_username', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
|
||||
setcookie('oc_token', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
|
||||
setcookie('oc_remember_login', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
|
||||
unset($_COOKIE['nc_username']); //TODO: DI
|
||||
unset($_COOKIE['nc_token']);
|
||||
unset($_COOKIE['nc_session_id']);
|
||||
setcookie('nc_username', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
|
||||
setcookie('nc_token', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
|
||||
setcookie('nc_session_id', '', time() - 3600, OC::$WEBROOT, '', $secureCookie, true);
|
||||
// old cookies might be stored under /webroot/ instead of /webroot
|
||||
// and Firefox doesn't like it!
|
||||
setcookie('oc_username', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
|
||||
setcookie('oc_token', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
|
||||
setcookie('oc_remember_login', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
|
||||
setcookie('nc_username', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
|
||||
setcookie('nc_token', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
|
||||
setcookie('nc_session_id', '', time() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -779,4 +810,5 @@ class Session implements IUserSession, Emitter {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -155,10 +155,11 @@ class OC_User {
|
|||
* @deprecated use \OCP\IUserSession::loginWithCookie()
|
||||
* @param string $uid The username of the user to log in
|
||||
* @param string $token
|
||||
* @param string $oldSessionId
|
||||
* @return bool
|
||||
*/
|
||||
public static function loginWithCookie($uid, $token) {
|
||||
return self::getUserSession()->loginWithCookie($uid, $token);
|
||||
public static function loginWithCookie($uid, $token, $oldSessionId) {
|
||||
return self::getUserSession()->loginWithCookie($uid, $token, $oldSessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -145,7 +145,7 @@ interface IRequest {
|
|||
* Shortcut for getting cookie variables
|
||||
*
|
||||
* @param string $key the key that will be taken from the $_COOKIE array
|
||||
* @return string the value in the $_COOKIE element
|
||||
* @return string|null the value in the $_COOKIE element
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public function getCookie($key);
|
||||
|
|
|
@ -322,6 +322,8 @@ class LoginControllerTest extends TestCase {
|
|||
|
||||
$this->userSession->expects($this->never())
|
||||
->method('createSessionToken');
|
||||
$this->userSession->expects($this->never())
|
||||
->method('createRememberMeToken');
|
||||
$this->config->expects($this->never())
|
||||
->method('deleteUserValue');
|
||||
|
||||
|
@ -363,7 +365,7 @@ class LoginControllerTest extends TestCase {
|
|||
->with($user, $password);
|
||||
$this->userSession->expects($this->once())
|
||||
->method('createSessionToken')
|
||||
->with($this->request, $user->getUID(), $user, $password);
|
||||
->with($this->request, $user->getUID(), $user, $password, false);
|
||||
$this->twoFactorManager->expects($this->once())
|
||||
->method('isTwoFactorAuthenticated')
|
||||
->with($user)
|
||||
|
@ -371,11 +373,63 @@ class LoginControllerTest extends TestCase {
|
|||
$this->config->expects($this->once())
|
||||
->method('deleteUserValue')
|
||||
->with('uid', 'core', 'lostpassword');
|
||||
$this->userSession->expects($this->never())
|
||||
->method('createRememberMeToken');
|
||||
|
||||
$expected = new \OCP\AppFramework\Http\RedirectResponse($indexPageUrl);
|
||||
$this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null));
|
||||
}
|
||||
|
||||
public function testLoginWithValidCredentialsAndRememberMe() {
|
||||
/** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
|
||||
$user = $this->getMockBuilder('\OCP\IUser')->getMock();
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('uid'));
|
||||
$password = 'secret';
|
||||
$indexPageUrl = \OC_Util::getDefaultPageUrl();
|
||||
|
||||
$this->request
|
||||
->expects($this->exactly(2))
|
||||
->method('getRemoteAddress')
|
||||
->willReturn('192.168.0.1');
|
||||
$this->request
|
||||
->expects($this->once())
|
||||
->method('passesCSRFCheck')
|
||||
->willReturn(true);
|
||||
$this->throttler
|
||||
->expects($this->once())
|
||||
->method('sleepDelay')
|
||||
->with('192.168.0.1');
|
||||
$this->throttler
|
||||
->expects($this->once())
|
||||
->method('getDelay')
|
||||
->with('192.168.0.1')
|
||||
->willReturn(200);
|
||||
$this->userManager->expects($this->once())
|
||||
->method('checkPassword')
|
||||
->will($this->returnValue($user));
|
||||
$this->userSession->expects($this->once())
|
||||
->method('login')
|
||||
->with($user, $password);
|
||||
$this->userSession->expects($this->once())
|
||||
->method('createSessionToken')
|
||||
->with($this->request, $user->getUID(), $user, $password, true);
|
||||
$this->twoFactorManager->expects($this->once())
|
||||
->method('isTwoFactorAuthenticated')
|
||||
->with($user)
|
||||
->will($this->returnValue(false));
|
||||
$this->config->expects($this->once())
|
||||
->method('deleteUserValue')
|
||||
->with('uid', 'core', 'lostpassword');
|
||||
$this->userSession->expects($this->once())
|
||||
->method('createRememberMeToken')
|
||||
->with($user);
|
||||
|
||||
$expected = new \OCP\AppFramework\Http\RedirectResponse($indexPageUrl);
|
||||
$this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null, true));
|
||||
}
|
||||
|
||||
public function testLoginWithoutPassedCsrfCheckAndNotLoggedIn() {
|
||||
/** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */
|
||||
$user = $this->getMockBuilder('\OCP\IUser')->getMock();
|
||||
|
@ -408,6 +462,8 @@ class LoginControllerTest extends TestCase {
|
|||
->will($this->returnValue(false));
|
||||
$this->config->expects($this->never())
|
||||
->method('deleteUserValue');
|
||||
$this->userSession->expects($this->never())
|
||||
->method('createRememberMeToken');
|
||||
|
||||
$expected = new \OCP\AppFramework\Http\RedirectResponse(\OC_Util::getDefaultPageUrl());
|
||||
$this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl));
|
||||
|
@ -450,6 +506,8 @@ class LoginControllerTest extends TestCase {
|
|||
->will($this->returnValue($redirectUrl));
|
||||
$this->config->expects($this->never())
|
||||
->method('deleteUserValue');
|
||||
$this->userSession->expects($this->never())
|
||||
->method('createRememberMeToken');
|
||||
|
||||
$expected = new \OCP\AppFramework\Http\RedirectResponse($redirectUrl);
|
||||
$this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl));
|
||||
|
@ -488,7 +546,7 @@ class LoginControllerTest extends TestCase {
|
|||
->will($this->returnValue($user));
|
||||
$this->userSession->expects($this->once())
|
||||
->method('createSessionToken')
|
||||
->with($this->request, $user->getUID(), 'Jane', $password);
|
||||
->with($this->request, $user->getUID(), 'Jane', $password, false);
|
||||
$this->userSession->expects($this->once())
|
||||
->method('isLoggedIn')
|
||||
->with()
|
||||
|
@ -540,7 +598,7 @@ class LoginControllerTest extends TestCase {
|
|||
->with('john@doe.com', $password);
|
||||
$this->userSession->expects($this->once())
|
||||
->method('createSessionToken')
|
||||
->with($this->request, $user->getUID(), 'john@doe.com', $password);
|
||||
->with($this->request, $user->getUID(), 'john@doe.com', $password, false);
|
||||
$this->twoFactorManager->expects($this->once())
|
||||
->method('isTwoFactorAuthenticated')
|
||||
->with($user)
|
||||
|
@ -564,6 +622,8 @@ class LoginControllerTest extends TestCase {
|
|||
$this->config->expects($this->once())
|
||||
->method('deleteUserValue')
|
||||
->with('john', 'core', 'lostpassword');
|
||||
$this->userSession->expects($this->never())
|
||||
->method('createRememberMeToken');
|
||||
|
||||
$expected = new RedirectResponse($challengeUrl);
|
||||
$this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', $password, null));
|
||||
|
@ -605,7 +665,7 @@ class LoginControllerTest extends TestCase {
|
|||
->with('john@doe.com', $password);
|
||||
$this->userSession->expects($this->once())
|
||||
->method('createSessionToken')
|
||||
->with($this->request, $user->getUID(), 'john@doe.com', $password);
|
||||
->with($this->request, $user->getUID(), 'john@doe.com', $password, false);
|
||||
$this->twoFactorManager->expects($this->once())
|
||||
->method('isTwoFactorAuthenticated')
|
||||
->with($user)
|
||||
|
@ -628,6 +688,8 @@ class LoginControllerTest extends TestCase {
|
|||
$this->config->expects($this->once())
|
||||
->method('deleteUserValue')
|
||||
->with('john', 'core', 'lostpassword');
|
||||
$this->userSession->expects($this->never())
|
||||
->method('createRememberMeToken');
|
||||
|
||||
$expected = new RedirectResponse($challengeUrl);
|
||||
$this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', $password, null));
|
||||
|
@ -680,6 +742,8 @@ class LoginControllerTest extends TestCase {
|
|||
->with('login', '192.168.0.1', ['user' => 'john@doe.com']);
|
||||
$this->config->expects($this->never())
|
||||
->method('deleteUserValue');
|
||||
$this->userSession->expects($this->never())
|
||||
->method('createRememberMeToken');
|
||||
|
||||
$expected = new RedirectResponse('');
|
||||
$this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', 'just wrong', null));
|
||||
|
|
|
@ -130,6 +130,7 @@ class DefaultTokenMapperTest extends TestCase {
|
|||
$token->setName('Firefox on Android');
|
||||
$token->setToken('1504445f1524fc801035448a95681a9378ba2e83930c814546c56e5d6ebde221198792fd900c88ed5ead0555780dad1ebce3370d7e154941cd5de87eb419899b');
|
||||
$token->setType(IToken::TEMPORARY_TOKEN);
|
||||
$token->setRemember(IToken::DO_NOT_REMEMBER);
|
||||
$token->setLastActivity($this->time - 60 * 60 * 24 * 3);
|
||||
$token->setLastCheck($this->time - 10);
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ namespace Test\Authentication\Token;
|
|||
use OC\Authentication\Token\DefaultToken;
|
||||
use OC\Authentication\Token\DefaultTokenProvider;
|
||||
use OC\Authentication\Token\IToken;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
|
@ -81,6 +80,7 @@ class DefaultTokenProviderTest extends TestCase {
|
|||
$toInsert->setName($name);
|
||||
$toInsert->setToken(hash('sha512', $token . '1f4h9s'));
|
||||
$toInsert->setType($type);
|
||||
$toInsert->setRemember(IToken::DO_NOT_REMEMBER);
|
||||
$toInsert->setLastActivity($this->time);
|
||||
|
||||
$this->config->expects($this->any())
|
||||
|
@ -95,7 +95,7 @@ class DefaultTokenProviderTest extends TestCase {
|
|||
->method('insert')
|
||||
->with($this->equalTo($toInsert));
|
||||
|
||||
$actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type);
|
||||
$actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type, IToken::DO_NOT_REMEMBER);
|
||||
|
||||
$this->assertEquals($toInsert, $actual);
|
||||
}
|
||||
|
@ -245,13 +245,19 @@ class DefaultTokenProviderTest extends TestCase {
|
|||
|
||||
public function testInvalidateOldTokens() {
|
||||
$defaultSessionLifetime = 60 * 60 * 24;
|
||||
$this->config->expects($this->once())
|
||||
$defaultRememberMeLifetime = 60 * 60 * 24 * 15;
|
||||
$this->config->expects($this->exactly(2))
|
||||
->method('getSystemValue')
|
||||
->with('session_lifetime', $defaultSessionLifetime)
|
||||
->will($this->returnValue(150));
|
||||
$this->mapper->expects($this->once())
|
||||
->will($this->returnValueMap([
|
||||
['session_lifetime', $defaultSessionLifetime, 150],
|
||||
['remember_login_cookie_lifetime', $defaultRememberMeLifetime, 300],
|
||||
]));
|
||||
$this->mapper->expects($this->at(0))
|
||||
->method('invalidateOld')
|
||||
->with($this->time - 150);
|
||||
$this->mapper->expects($this->at(1))
|
||||
->method('invalidateOld')
|
||||
->with($this->time - 300);
|
||||
|
||||
$this->tokenProvider->invalidateOldTokens();
|
||||
}
|
||||
|
|
|
@ -233,8 +233,15 @@ class ManagerTest extends TestCase {
|
|||
->with($this->user, $challenge)
|
||||
->will($this->returnValue(true));
|
||||
$this->session->expects($this->once())
|
||||
->method('get')
|
||||
->with('two_factor_remember_login')
|
||||
->will($this->returnValue(false));
|
||||
$this->session->expects($this->at(1))
|
||||
->method('remove')
|
||||
->with('two_factor_auth_uid');
|
||||
$this->session->expects($this->at(2))
|
||||
->method('remove')
|
||||
->with('two_factor_remember_login');
|
||||
|
||||
$this->assertTrue($this->manager->verifyChallenge('email', $this->user, $challenge));
|
||||
}
|
||||
|
@ -304,11 +311,29 @@ class ManagerTest extends TestCase {
|
|||
->method('getUID')
|
||||
->will($this->returnValue('ferdinand'));
|
||||
|
||||
$this->session->expects($this->once())
|
||||
$this->session->expects($this->at(0))
|
||||
->method('set')
|
||||
->with('two_factor_auth_uid', 'ferdinand');
|
||||
$this->session->expects($this->at(1))
|
||||
->method('set')
|
||||
->with('two_factor_remember_login', true);
|
||||
|
||||
$this->manager->prepareTwoFactorLogin($this->user);
|
||||
$this->manager->prepareTwoFactorLogin($this->user, true);
|
||||
}
|
||||
|
||||
public function testPrepareTwoFactorLoginDontRemember() {
|
||||
$this->user->expects($this->once())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('ferdinand'));
|
||||
|
||||
$this->session->expects($this->at(0))
|
||||
->method('set')
|
||||
->with('two_factor_auth_uid', 'ferdinand');
|
||||
$this->session->expects($this->at(1))
|
||||
->method('set')
|
||||
->with('two_factor_remember_login', false);
|
||||
|
||||
$this->manager->prepareTwoFactorLogin($this->user, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ class SessionTest extends \Test\TestCase {
|
|||
$this->tokenProvider = $this->createMock(IProvider::class);
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->throttler = $this->createMock(Throttler::class);
|
||||
|
||||
\OC_User::setIncognitoMode(false);
|
||||
}
|
||||
|
||||
public function testGetUser() {
|
||||
|
@ -100,7 +102,7 @@ class SessionTest extends \Test\TestCase {
|
|||
->method('updateTokenActivity')
|
||||
->with($token);
|
||||
|
||||
$manager->expects($this->any())
|
||||
$manager->expects($this->once())
|
||||
->method('get')
|
||||
->with($expectedUser->getUID())
|
||||
->will($this->returnValue($expectedUser));
|
||||
|
@ -181,16 +183,9 @@ class SessionTest extends \Test\TestCase {
|
|||
}, 'foo'));
|
||||
|
||||
$managerMethods = get_class_methods(Manager::class);
|
||||
//keep following methods intact in order to ensure hooks are
|
||||
//working
|
||||
$doNotMock = array('__construct', 'emit', 'listen');
|
||||
foreach ($doNotMock as $methodName) {
|
||||
$i = array_search($methodName, $managerMethods, true);
|
||||
if ($i !== false) {
|
||||
unset($managerMethods[$i]);
|
||||
}
|
||||
}
|
||||
$manager = $this->getMockBuilder(Manager::class)
|
||||
//keep following methods intact in order to ensure hooks are working
|
||||
$mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
|
||||
$manager = $this->getMockBuilder(Manager::class)->setMethods($mockedManagerMethods)->getMock();
|
||||
->setMethods($managerMethods)
|
||||
->setConstructorArgs([$this->config])
|
||||
->getMock();
|
||||
|
@ -238,17 +233,10 @@ class SessionTest extends \Test\TestCase {
|
|||
->with('bar')
|
||||
->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
|
||||
|
||||
$managerMethods = get_class_methods('\OC\User\Manager');
|
||||
//keep following methods intact in order to ensure hooks are
|
||||
//working
|
||||
$doNotMock = array('__construct', 'emit', 'listen');
|
||||
foreach ($doNotMock as $methodName) {
|
||||
$i = array_search($methodName, $managerMethods, true);
|
||||
if ($i !== false) {
|
||||
unset($managerMethods[$i]);
|
||||
}
|
||||
}
|
||||
$manager = $this->getMockBuilder(Manager::class)
|
||||
$managerMethods = get_class_methods(\OC\User\Manager::class);
|
||||
//keep following methods intact in order to ensure hooks are working
|
||||
$mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
|
||||
$manager = $this->getMockBuilder(Manager::class)->setMethods($mockedManagerMethods)->getMock();
|
||||
->setMethods($managerMethods)
|
||||
->setConstructorArgs([$this->config])
|
||||
->getMock();
|
||||
|
@ -273,17 +261,10 @@ class SessionTest extends \Test\TestCase {
|
|||
|
||||
public function testLoginInvalidPassword() {
|
||||
$session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
|
||||
$managerMethods = get_class_methods('\OC\User\Manager');
|
||||
//keep following methods intact in order to ensure hooks are
|
||||
//working
|
||||
$doNotMock = array('__construct', 'emit', 'listen');
|
||||
foreach ($doNotMock as $methodName) {
|
||||
$i = array_search($methodName, $managerMethods, true);
|
||||
if ($i !== false) {
|
||||
unset($managerMethods[$i]);
|
||||
}
|
||||
}
|
||||
$manager = $this->getMockBuilder(Manager::class)
|
||||
$managerMethods = get_class_methods(\OC\User\Manager::class);
|
||||
//keep following methods intact in order to ensure hooks are working
|
||||
$mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
|
||||
$manager = $this->getMockBuilder(Manager::class)->setMethods($mockedManagerMethods)->getMock();
|
||||
->setMethods($managerMethods)
|
||||
->setConstructorArgs([$this->config])
|
||||
->getMock();
|
||||
|
@ -513,156 +494,208 @@ class SessionTest extends \Test\TestCase {
|
|||
|
||||
public function testRememberLoginValidToken() {
|
||||
$session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
|
||||
$session->expects($this->exactly(1))
|
||||
->method('set')
|
||||
->with($this->callback(function ($key) {
|
||||
switch ($key) {
|
||||
case 'user_id':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}, 'foo'));
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
$managerMethods = get_class_methods(\OC\User\Manager::class);
|
||||
//keep following methods intact in order to ensure hooks are working
|
||||
$mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
|
||||
$manager = $this->getMockBuilder(Manager::class)->setMethods($mockedManagerMethods)->getMock();
|
||||
$userSession = $this->getMockBuilder(Session::class)
|
||||
//override, otherwise tests will fail because of setcookie()
|
||||
->setMethods(['setMagicInCookie'])
|
||||
->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
|
||||
->getMock();
|
||||
|
||||
$managerMethods = get_class_methods(Manager::class);
|
||||
//keep following methods intact in order to ensure hooks are
|
||||
//working
|
||||
$doNotMock = array('__construct', 'emit', 'listen');
|
||||
foreach ($doNotMock as $methodName) {
|
||||
$i = array_search($methodName, $managerMethods, true);
|
||||
if ($i !== false) {
|
||||
unset($managerMethods[$i]);
|
||||
}
|
||||
}
|
||||
$manager = $this->getMockBuilder(Manager::class)
|
||||
$user = $this->createMock(IUser::class);
|
||||
$token = 'goodToken';
|
||||
$oldSessionId = 'sess321';
|
||||
$sessionId = 'sess123';
|
||||
->setMethods($managerMethods)
|
||||
->setConstructorArgs([$this->config])
|
||||
->getMock();
|
||||
|
||||
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
||||
|
||||
$user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
|
||||
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('foo'));
|
||||
$user->expects($this->once())
|
||||
->method('updateLastLoginTimestamp');
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
$manager->expects($this->once())
|
||||
->method('get')
|
||||
->with('foo')
|
||||
->will($this->returnValue($user));
|
||||
$this->config->expects($this->once())
|
||||
->method('getUserKeys')
|
||||
->with('foo', 'login_token')
|
||||
->will($this->returnValue([$token]));
|
||||
$this->config->expects($this->once())
|
||||
->method('deleteUserValue')
|
||||
->with('foo', 'login_token', $token);
|
||||
$this->config->expects($this->once())
|
||||
->method('setUserValue'); // TODO: mock new random value
|
||||
|
||||
//prepare login token
|
||||
$token = 'goodToken';
|
||||
\OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
|
||||
$session->expects($this->once())
|
||||
->method('getId')
|
||||
->will($this->returnValue($sessionId));
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('renewSessionToken')
|
||||
->with($oldSessionId, $sessionId)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('foo'));
|
||||
$userSession->expects($this->once())
|
||||
->method('setMagicInCookie');
|
||||
$user->expects($this->once())
|
||||
->method('updateLastLoginTimestamp');
|
||||
$session->expects($this->once())
|
||||
->method('set')
|
||||
->with('user_id', 'foo');
|
||||
|
||||
$granted = $userSession->loginWithCookie('foo', $token, $oldSessionId);
|
||||
|
||||
$this->assertTrue($granted);
|
||||
}
|
||||
|
||||
public function testRememberLoginInvalidSessionToken() {
|
||||
$session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
|
||||
$managerMethods = get_class_methods(\OC\User\Manager::class);
|
||||
//keep following methods intact in order to ensure hooks are working
|
||||
$mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
|
||||
$manager = $this->getMockBuilder(Manager::class)->setMethods($mockedManagerMethods)->getMock();
|
||||
$userSession = $this->getMockBuilder(Session::class)
|
||||
//override, otherwise tests will fail because of setcookie()
|
||||
->setMethods(['setMagicInCookie'])
|
||||
//there are passed as parameters to the constructor
|
||||
->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
|
||||
->getMock();
|
||||
|
||||
$granted = $userSession->loginWithCookie('foo', $token);
|
||||
$user = $this->createMock(IUser::class);
|
||||
$token = 'goodToken';
|
||||
$oldSessionId = 'sess321';
|
||||
$sessionId = 'sess123';
|
||||
|
||||
$this->assertSame($granted, true);
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
$manager->expects($this->once())
|
||||
->method('get')
|
||||
->with('foo')
|
||||
->will($this->returnValue($user));
|
||||
$this->config->expects($this->once())
|
||||
->method('getUserKeys')
|
||||
->with('foo', 'login_token')
|
||||
->will($this->returnValue([$token]));
|
||||
$this->config->expects($this->once())
|
||||
->method('deleteUserValue')
|
||||
->with('foo', 'login_token', $token);
|
||||
$this->config->expects($this->once())
|
||||
->method('setUserValue'); // TODO: mock new random value
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('getId')
|
||||
->will($this->returnValue($sessionId));
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('renewSessionToken')
|
||||
->with($oldSessionId, $sessionId)
|
||||
->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
|
||||
->setMethods($managerMethods)
|
||||
->setConstructorArgs([$this->config])
|
||||
->getMock();
|
||||
|
||||
$user->expects($this->never())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('foo'));
|
||||
$userSession->expects($this->never())
|
||||
->method('setMagicInCookie');
|
||||
$user->expects($this->never())
|
||||
->method('updateLastLoginTimestamp');
|
||||
$session->expects($this->never())
|
||||
->method('set')
|
||||
->with('user_id', 'foo');
|
||||
|
||||
$granted = $userSession->loginWithCookie('foo', $token, $oldSessionId);
|
||||
|
||||
$this->assertFalse($granted);
|
||||
}
|
||||
|
||||
public function testRememberLoginInvalidToken() {
|
||||
$session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
|
||||
$session->expects($this->never())
|
||||
->method('set');
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
|
||||
$managerMethods = get_class_methods('\OC\User\Manager');
|
||||
//keep following methods intact in order to ensure hooks are
|
||||
//working
|
||||
$doNotMock = array('__construct', 'emit', 'listen');
|
||||
foreach ($doNotMock as $methodName) {
|
||||
$i = array_search($methodName, $managerMethods, true);
|
||||
if ($i !== false) {
|
||||
unset($managerMethods[$i]);
|
||||
}
|
||||
}
|
||||
$manager = $this->getMockBuilder(Manager::class)
|
||||
->setMethods($managerMethods)
|
||||
->setConstructorArgs([$this->config])
|
||||
$managerMethods = get_class_methods(\OC\User\Manager::class);
|
||||
//keep following methods intact in order to ensure hooks are working
|
||||
$mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
|
||||
$manager = $this->getMockBuilder(Manager::class)->setMethods($mockedManagerMethods)->getMock();
|
||||
$userSession = $this->getMockBuilder(Session::class)
|
||||
//override, otherwise tests will fail because of setcookie()
|
||||
->setMethods(['setMagicInCookie'])
|
||||
->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
|
||||
->getMock();
|
||||
|
||||
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
||||
|
||||
$user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
|
||||
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('foo'));
|
||||
$user->expects($this->never())
|
||||
->method('updateLastLoginTimestamp');
|
||||
$user = $this->createMock(IUser::class);
|
||||
$token = 'goodToken';
|
||||
$oldSessionId = 'sess321';
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
$manager->expects($this->once())
|
||||
->method('get')
|
||||
->with('foo')
|
||||
->will($this->returnValue($user));
|
||||
$this->config->expects($this->once())
|
||||
->method('getUserKeys')
|
||||
->with('foo', 'login_token')
|
||||
->will($this->returnValue(['anothertoken']));
|
||||
$this->config->expects($this->never())
|
||||
->method('deleteUserValue')
|
||||
->with('foo', 'login_token', $token);
|
||||
|
||||
//prepare login token
|
||||
$token = 'goodToken';
|
||||
\OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
|
||||
$this->tokenProvider->expects($this->never())
|
||||
->method('renewSessionToken');
|
||||
$userSession->expects($this->never())
|
||||
->method('setMagicInCookie');
|
||||
$user->expects($this->never())
|
||||
->method('updateLastLoginTimestamp');
|
||||
$session->expects($this->never())
|
||||
->method('set')
|
||||
->with('user_id', 'foo');
|
||||
|
||||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
|
||||
$granted = $userSession->loginWithCookie('foo', 'badToken');
|
||||
$granted = $userSession->loginWithCookie('foo', $token, $oldSessionId);
|
||||
|
||||
$this->assertSame($granted, false);
|
||||
$this->assertFalse($granted);
|
||||
}
|
||||
|
||||
public function testRememberLoginInvalidUser() {
|
||||
$session = $this->getMockBuilder(Memory::class)->setConstructorArgs([''])->getMock();
|
||||
$session->expects($this->never())
|
||||
->method('set');
|
||||
$managerMethods = get_class_methods(\OC\User\Manager::class);
|
||||
//keep following methods intact in order to ensure hooks are working
|
||||
$mockedManagerMethods = array_diff($managerMethods, ['__construct', 'emit', 'listen']);
|
||||
$manager = $this->getMockBuilder(Manager::class)->setMethods($mockedManagerMethods)->getMock();
|
||||
$userSession = $this->getMockBuilder(Session::class)
|
||||
//override, otherwise tests will fail because of setcookie()
|
||||
->setMethods(['setMagicInCookie'])
|
||||
->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
|
||||
->getMock();
|
||||
$token = 'goodToken';
|
||||
$oldSessionId = 'sess321';
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
|
||||
$managerMethods = get_class_methods('\OC\User\Manager');
|
||||
//keep following methods intact in order to ensure hooks are
|
||||
//working
|
||||
$doNotMock = array('__construct', 'emit', 'listen');
|
||||
foreach ($doNotMock as $methodName) {
|
||||
$i = array_search($methodName, $managerMethods, true);
|
||||
if ($i !== false) {
|
||||
unset($managerMethods[$i]);
|
||||
}
|
||||
}
|
||||
$manager = $this->getMockBuilder(Manager::class)
|
||||
->setMethods($managerMethods)
|
||||
->setConstructorArgs([$this->config])
|
||||
->getMock();
|
||||
|
||||
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
||||
|
||||
$user = $this->getMockBuilder(User::class)->setConstructorArgs(['foo', $backend])->getMock();
|
||||
|
||||
$user->expects($this->never())
|
||||
->method('getUID');
|
||||
$user->expects($this->never())
|
||||
->method('updateLastLoginTimestamp');
|
||||
|
||||
$manager->expects($this->once())
|
||||
->method('get')
|
||||
->with('foo')
|
||||
->will($this->returnValue(null));
|
||||
$this->config->expects($this->never())
|
||||
->method('getUserKeys')
|
||||
->with('foo', 'login_token')
|
||||
->will($this->returnValue(['anothertoken']));
|
||||
|
||||
//prepare login token
|
||||
$token = 'goodToken';
|
||||
\OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
|
||||
$this->tokenProvider->expects($this->never())
|
||||
->method('renewSessionToken');
|
||||
$userSession->expects($this->never())
|
||||
->method('setMagicInCookie');
|
||||
$session->expects($this->never())
|
||||
->method('set')
|
||||
->with('user_id', 'foo');
|
||||
|
||||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
|
||||
$granted = $userSession->loginWithCookie('foo', $token);
|
||||
$granted = $userSession->loginWithCookie('foo', $token, $oldSessionId);
|
||||
|
||||
$this->assertSame($granted, false);
|
||||
$this->assertFalse($granted);
|
||||
}
|
||||
|
||||
public function testActiveUserAfterSetSession() {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
|
||||
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
|
||||
// when updating major/minor version number.
|
||||
$OC_Version = array(9, 2, 0, 4);
|
||||
$OC_Version = array(9, 2, 0, 5);
|
||||
|
||||
// The human readable string
|
||||
$OC_VersionString = '11.0 alpha';
|
||||
|
|
Loading…
Reference in New Issue