Merge pull request #25172 from owncloud/token-login-validation
Token login validation
This commit is contained in:
commit
3db5de95bd
|
@ -1120,6 +1120,15 @@
|
|||
<length>4</length>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>last_check</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<unsigned>true</unsigned>
|
||||
<length>4</length>
|
||||
</field>
|
||||
|
||||
<index>
|
||||
<name>authtoken_token_index</name>
|
||||
<unique>true</unique>
|
||||
|
|
|
@ -74,6 +74,11 @@ class DefaultToken extends Entity implements IToken {
|
|||
*/
|
||||
protected $lastActivity;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $lastCheck;
|
||||
|
||||
public function getId() {
|
||||
return $this->id;
|
||||
}
|
||||
|
@ -109,4 +114,22 @@ class DefaultToken extends Entity implements IToken {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp of the last password check
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastCheck() {
|
||||
return parent::getLastCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp of the last password check
|
||||
*
|
||||
* @param int $time
|
||||
*/
|
||||
public function setLastCheck($time) {
|
||||
return parent::setLastCheck($time);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -70,7 +70,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')
|
||||
$result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check')
|
||||
->from('authtoken')
|
||||
->where($qb->expr()->eq('token', $qb->createParameter('token')))
|
||||
->setParameter('token', $token)
|
||||
|
@ -96,7 +96,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')
|
||||
$qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check')
|
||||
->from('authtoken')
|
||||
->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())))
|
||||
->setMaxResults(1000);
|
||||
|
|
|
@ -92,21 +92,36 @@ class DefaultTokenProvider implements IProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Update token activity timestamp
|
||||
* Save the updated token
|
||||
*
|
||||
* @throws InvalidTokenException
|
||||
* @param IToken $token
|
||||
*/
|
||||
public function updateToken(IToken $token) {
|
||||
if (!($token instanceof DefaultToken)) {
|
||||
throw new InvalidTokenException();
|
||||
}
|
||||
/** @var DefaultToken $token */
|
||||
$token->setLastActivity($this->time->getTime());
|
||||
|
||||
$this->mapper->update($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update token activity timestamp
|
||||
*
|
||||
* @throws InvalidTokenException
|
||||
* @param IToken $token
|
||||
*/
|
||||
public function updateTokenActivity(IToken $token) {
|
||||
if (!($token instanceof DefaultToken)) {
|
||||
throw new InvalidTokenException();
|
||||
}
|
||||
/** @var DefaultToken $token */
|
||||
$now = $this->time->getTime();
|
||||
if ($token->getLastActivity() < ($now - 60)) {
|
||||
// Update token only once per minute
|
||||
$token->setLastActivity($now);
|
||||
$this->mapper->update($token);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all token of a user
|
||||
*
|
||||
|
@ -195,21 +210,6 @@ class DefaultTokenProvider implements IProvider {
|
|||
$this->mapper->invalidateOld($olderThan);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
* @throws InvalidTokenException
|
||||
* @return DefaultToken user UID
|
||||
*/
|
||||
public function validateToken($token) {
|
||||
try {
|
||||
$dbToken = $this->mapper->getToken($this->hashToken($token));
|
||||
$this->logger->debug('valid default token for ' . $dbToken->getUID());
|
||||
return $dbToken;
|
||||
} catch (DoesNotExistException $ex) {
|
||||
throw new InvalidTokenException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
* @return string
|
||||
|
|
|
@ -49,13 +49,6 @@ interface IProvider {
|
|||
*/
|
||||
public function getToken($tokenId) ;
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
* @throws InvalidTokenException
|
||||
* @return IToken
|
||||
*/
|
||||
public function validateToken($token);
|
||||
|
||||
/**
|
||||
* Invalidate (delete) the given session token
|
||||
*
|
||||
|
@ -72,12 +65,19 @@ interface IProvider {
|
|||
public function invalidateTokenById(IUser $user, $id);
|
||||
|
||||
/**
|
||||
* Update token activity timestamp
|
||||
* Save the updated token
|
||||
*
|
||||
* @param IToken $token
|
||||
*/
|
||||
public function updateToken(IToken $token);
|
||||
|
||||
/**
|
||||
* Update token activity timestamp
|
||||
*
|
||||
* @param IToken $token
|
||||
*/
|
||||
public function updateTokenActivity(IToken $token);
|
||||
|
||||
/**
|
||||
* Get all token of a user
|
||||
*
|
||||
|
|
|
@ -55,4 +55,18 @@ interface IToken extends JsonSerializable {
|
|||
* @return string
|
||||
*/
|
||||
public function getPassword();
|
||||
|
||||
/**
|
||||
* Get the timestamp of the last password check
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastCheck();
|
||||
|
||||
/**
|
||||
* Get the timestamp of the last password check
|
||||
*
|
||||
* @param int $time
|
||||
*/
|
||||
public function setLastCheck($time);
|
||||
}
|
||||
|
|
|
@ -193,53 +193,35 @@ class Session implements IUserSession, Emitter {
|
|||
if (is_null($this->activeUser)) {
|
||||
return null;
|
||||
}
|
||||
$this->validateSession($this->activeUser);
|
||||
$this->validateSession();
|
||||
}
|
||||
return $this->activeUser;
|
||||
}
|
||||
|
||||
protected function validateSession(IUser $user) {
|
||||
try {
|
||||
$sessionId = $this->session->getId();
|
||||
} catch (SessionNotAvailableException $ex) {
|
||||
return;
|
||||
/**
|
||||
* Validate whether the current session is valid
|
||||
*
|
||||
* - For token-authenticated clients, the token validity is checked
|
||||
* - For browsers, the session token validity is checked
|
||||
*/
|
||||
protected function validateSession() {
|
||||
$token = null;
|
||||
$appPassword = $this->session->get('app_password');
|
||||
|
||||
if (is_null($appPassword)) {
|
||||
try {
|
||||
$token = $this->session->getId();
|
||||
} catch (SessionNotAvailableException $ex) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$token = $appPassword;
|
||||
}
|
||||
try {
|
||||
$token = $this->tokenProvider->getToken($sessionId);
|
||||
} catch (InvalidTokenException $ex) {
|
||||
|
||||
if (!$this->validateToken($token)) {
|
||||
// Session was invalidated
|
||||
$this->logout();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether login credentials are still valid and the user was not disabled
|
||||
// This check is performed each 5 minutes
|
||||
$lastCheck = $this->session->get('last_login_check') ? : 0;
|
||||
$now = $this->timeFacory->getTime();
|
||||
if ($lastCheck < ($now - 60 * 5)) {
|
||||
try {
|
||||
$pwd = $this->tokenProvider->getPassword($token, $sessionId);
|
||||
} catch (InvalidTokenException $ex) {
|
||||
// An invalid token password was used -> log user out
|
||||
$this->logout();
|
||||
return;
|
||||
} catch (PasswordlessTokenException $ex) {
|
||||
// Token has no password, nothing to check
|
||||
$this->session->set('last_login_check', $now);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->manager->checkPassword($token->getLoginName(), $pwd) === false
|
||||
|| !$user->isEnabled()) {
|
||||
// Password has changed or user was disabled -> log user out
|
||||
$this->logout();
|
||||
return;
|
||||
}
|
||||
$this->session->set('last_login_check', $now);
|
||||
}
|
||||
|
||||
// Session is valid, so the token can be refreshed
|
||||
$this->updateToken($token);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -299,20 +281,21 @@ class Session implements IUserSession, Emitter {
|
|||
public function login($uid, $password) {
|
||||
$this->session->regenerateId();
|
||||
if ($this->validateToken($password)) {
|
||||
$user = $this->getUser();
|
||||
|
||||
// When logging in with token, the password must be decrypted first before passing to login hook
|
||||
try {
|
||||
$token = $this->tokenProvider->getToken($password);
|
||||
try {
|
||||
$password = $this->tokenProvider->getPassword($token, $password);
|
||||
$this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
|
||||
$loginPassword = $this->tokenProvider->getPassword($token, $password);
|
||||
$this->manager->emit('\OC\User', 'preLogin', array($uid, $loginPassword));
|
||||
} catch (PasswordlessTokenException $ex) {
|
||||
$this->manager->emit('\OC\User', 'preLogin', array($uid, ''));
|
||||
}
|
||||
} catch (InvalidTokenException $ex) {
|
||||
// Invalid token, nothing to do
|
||||
}
|
||||
|
||||
$this->loginWithToken($password);
|
||||
$user = $this->getUser();
|
||||
} else {
|
||||
$this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
|
||||
$user = $this->manager->checkPassword($uid, $password);
|
||||
|
@ -370,7 +353,10 @@ class Session implements IUserSession, Emitter {
|
|||
return false;
|
||||
}
|
||||
|
||||
if ($this->supportsCookies($request)) {
|
||||
if ($isTokenPassword) {
|
||||
$this->session->set('app_password', $password);
|
||||
} else if($this->supportsCookies($request)) {
|
||||
// Password login, but cookies supported -> create (browser) session token
|
||||
$this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
|
||||
}
|
||||
|
||||
|
@ -463,8 +449,22 @@ class Session implements IUserSession, Emitter {
|
|||
return false;
|
||||
}
|
||||
|
||||
private function loginWithToken($uid) {
|
||||
// TODO: $this->manager->emit('\OC\User', 'preTokenLogin', array($uid));
|
||||
private function loginWithToken($token) {
|
||||
try {
|
||||
$dbToken = $this->tokenProvider->getToken($token);
|
||||
} catch (InvalidTokenException $ex) {
|
||||
return false;
|
||||
}
|
||||
$uid = $dbToken->getUID();
|
||||
|
||||
$password = '';
|
||||
try {
|
||||
$password = $this->tokenProvider->getPassword($dbToken, $token);
|
||||
} catch (PasswordlessTokenException $ex) {
|
||||
// Ignore and use empty string instead
|
||||
}
|
||||
$this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
|
||||
|
||||
$user = $this->manager->get($uid);
|
||||
if (is_null($user)) {
|
||||
// user does not exist
|
||||
|
@ -477,7 +477,8 @@ class Session implements IUserSession, Emitter {
|
|||
|
||||
//login
|
||||
$this->setUser($user);
|
||||
// TODO: $this->manager->emit('\OC\User', 'postTokenLogin', array($user));
|
||||
|
||||
$this->manager->emit('\OC\User', 'postLogin', array($user, $password));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -534,37 +535,71 @@ class Session implements IUserSession, Emitter {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param IToken $dbToken
|
||||
* @param string $token
|
||||
* @return boolean
|
||||
*/
|
||||
private function checkTokenCredentials(IToken $dbToken, $token) {
|
||||
// Check whether login credentials are still valid and the user was not disabled
|
||||
// This check is performed each 5 minutes
|
||||
$lastCheck = $dbToken->getLastCheck() ? : 0;
|
||||
$now = $this->timeFacory->getTime();
|
||||
if ($lastCheck > ($now - 60 * 5)) {
|
||||
// Checked performed recently, nothing to do now
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
$pwd = $this->tokenProvider->getPassword($dbToken, $token);
|
||||
} catch (InvalidTokenException $ex) {
|
||||
// An invalid token password was used -> log user out
|
||||
return false;
|
||||
} catch (PasswordlessTokenException $ex) {
|
||||
// Token has no password
|
||||
|
||||
if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) {
|
||||
$this->tokenProvider->invalidateToken($token);
|
||||
return false;
|
||||
}
|
||||
|
||||
$dbToken->setLastCheck($now);
|
||||
$this->tokenProvider->updateToken($dbToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->manager->checkPassword($dbToken->getLoginName(), $pwd) === false
|
||||
|| (!is_null($this->activeUser) && !$this->activeUser->isEnabled())) {
|
||||
$this->tokenProvider->invalidateToken($token);
|
||||
// Password has changed or user was disabled -> log user out
|
||||
return false;
|
||||
}
|
||||
$dbToken->setLastCheck($now);
|
||||
$this->tokenProvider->updateToken($dbToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given token exists and performs password/user-enabled checks
|
||||
*
|
||||
* Invalidates the token if checks fail
|
||||
*
|
||||
* @param string $token
|
||||
* @return boolean
|
||||
*/
|
||||
private function validateToken($token) {
|
||||
try {
|
||||
$token = $this->tokenProvider->validateToken($token);
|
||||
if (!is_null($token)) {
|
||||
$result = $this->loginWithToken($token->getUID());
|
||||
if ($result) {
|
||||
// Login success
|
||||
$this->updateToken($token);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$dbToken = $this->tokenProvider->getToken($token);
|
||||
} catch (InvalidTokenException $ex) {
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IToken $token
|
||||
*/
|
||||
private function updateToken(IToken $token) {
|
||||
// To save unnecessary DB queries, this is only done once a minute
|
||||
$lastTokenUpdate = $this->session->get('last_token_update') ? : 0;
|
||||
$now = $this->timeFacory->getTime();
|
||||
if ($lastTokenUpdate < ($now - 60)) {
|
||||
$this->tokenProvider->updateToken($token);
|
||||
$this->session->set('last_token_update', $now);
|
||||
if (!$this->checkTokenCredentials($dbToken, $token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->tokenProvider->updateTokenActivity($dbToken);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -578,15 +613,21 @@ class Session implements IUserSession, Emitter {
|
|||
if (strpos($authHeader, 'token ') === false) {
|
||||
// No auth header, let's try session id
|
||||
try {
|
||||
$sessionId = $this->session->getId();
|
||||
return $this->validateToken($sessionId);
|
||||
$token = $this->session->getId();
|
||||
} catch (SessionNotAvailableException $ex) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$token = substr($authHeader, 6);
|
||||
return $this->validateToken($token);
|
||||
}
|
||||
|
||||
if (!$this->loginWithToken($token)) {
|
||||
return false;
|
||||
}
|
||||
if(!$this->validateToken($token)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -63,6 +63,7 @@ class DefaultTokenMapperTest extends TestCase {
|
|||
'token' => $qb->createNamedParameter('9c5a2e661482b65597408a6bb6c4a3d1af36337381872ac56e445a06cdb7fea2b1039db707545c11027a4966919918b19d875a8b774840b18c6cbb7ae56fe206'),
|
||||
'type' => $qb->createNamedParameter(IToken::TEMPORARY_TOKEN),
|
||||
'last_activity' => $qb->createNamedParameter($this->time - 120, IQueryBuilder::PARAM_INT), // Two minutes ago
|
||||
'last_check' => $this->time - 60 * 10, // 10mins ago
|
||||
])->execute();
|
||||
$qb->insert('authtoken')->values([
|
||||
'uid' => $qb->createNamedParameter('user2'),
|
||||
|
@ -72,6 +73,7 @@ class DefaultTokenMapperTest extends TestCase {
|
|||
'token' => $qb->createNamedParameter('1504445f1524fc801035448a95681a9378ba2e83930c814546c56e5d6ebde221198792fd900c88ed5ead0555780dad1ebce3370d7e154941cd5de87eb419899b'),
|
||||
'type' => $qb->createNamedParameter(IToken::TEMPORARY_TOKEN),
|
||||
'last_activity' => $qb->createNamedParameter($this->time - 60 * 60 * 24 * 3, IQueryBuilder::PARAM_INT), // Three days ago
|
||||
'last_check' => $this->time - 10, // 10secs ago
|
||||
])->execute();
|
||||
$qb->insert('authtoken')->values([
|
||||
'uid' => $qb->createNamedParameter('user1'),
|
||||
|
@ -81,6 +83,7 @@ class DefaultTokenMapperTest extends TestCase {
|
|||
'token' => $qb->createNamedParameter('47af8697ba590fb82579b5f1b3b6e8066773a62100abbe0db09a289a62f5d980dc300fa3d98b01d7228468d1ab05c1aa14c8d14bd5b6eee9cdf1ac14864680c3'),
|
||||
'type' => $qb->createNamedParameter(IToken::TEMPORARY_TOKEN),
|
||||
'last_activity' => $qb->createNamedParameter($this->time - 120, IQueryBuilder::PARAM_INT), // Two minutes ago
|
||||
'last_check' => $this->time - 60 * 10, // 10mins ago
|
||||
])->execute();
|
||||
}
|
||||
|
||||
|
@ -127,6 +130,7 @@ class DefaultTokenMapperTest extends TestCase {
|
|||
$token->setToken('1504445f1524fc801035448a95681a9378ba2e83930c814546c56e5d6ebde221198792fd900c88ed5ead0555780dad1ebce3370d7e154941cd5de87eb419899b');
|
||||
$token->setType(IToken::TEMPORARY_TOKEN);
|
||||
$token->setLastActivity($this->time - 60 * 60 * 24 * 3);
|
||||
$token->setLastCheck($this->time - 10);
|
||||
|
||||
$dbToken = $this->mapper->getToken($token->getToken());
|
||||
|
||||
|
|
|
@ -97,14 +97,25 @@ class DefaultTokenProviderTest extends TestCase {
|
|||
|
||||
public function testUpdateToken() {
|
||||
$tk = new DefaultToken();
|
||||
$tk->setLastActivity($this->time - 200);
|
||||
$this->mapper->expects($this->once())
|
||||
->method('update')
|
||||
->with($tk);
|
||||
|
||||
$this->tokenProvider->updateToken($tk);
|
||||
$this->tokenProvider->updateTokenActivity($tk);
|
||||
|
||||
$this->assertEquals($this->time, $tk->getLastActivity());
|
||||
}
|
||||
|
||||
public function testUpdateTokenDebounce() {
|
||||
$tk = new DefaultToken();
|
||||
$tk->setLastActivity($this->time - 30);
|
||||
$this->mapper->expects($this->never())
|
||||
->method('update')
|
||||
->with($tk);
|
||||
|
||||
$this->tokenProvider->updateTokenActivity($tk);
|
||||
}
|
||||
|
||||
public function testGetTokenByUser() {
|
||||
$user = $this->getMock('\OCP\IUser');
|
||||
|
@ -240,30 +251,4 @@ class DefaultTokenProviderTest extends TestCase {
|
|||
$this->tokenProvider->invalidateOldTokens();
|
||||
}
|
||||
|
||||
public function testValidateToken() {
|
||||
$token = 'sometoken';
|
||||
$dbToken = new DefaultToken();
|
||||
$this->mapper->expects($this->once())
|
||||
->method('getToken')
|
||||
->with(hash('sha512', $token))
|
||||
->will($this->returnValue($dbToken));
|
||||
|
||||
$actual = $this->tokenProvider->validateToken($token);
|
||||
|
||||
$this->assertEquals($dbToken, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \OC\Authentication\Exceptions\InvalidTokenException
|
||||
*/
|
||||
public function testValidateInvalidToken() {
|
||||
$token = 'sometoken';
|
||||
$this->mapper->expects($this->once())
|
||||
->method('getToken')
|
||||
->with(hash('sha512', $token))
|
||||
->will($this->throwException(new DoesNotExistException('')));
|
||||
|
||||
$this->tokenProvider->validateToken($token);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ class SessionTest extends \Test\TestCase {
|
|||
public function testGetUser() {
|
||||
$token = new \OC\Authentication\Token\DefaultToken();
|
||||
$token->setLoginName('User123');
|
||||
$token->setLastCheck(200);
|
||||
|
||||
$expectedUser = $this->getMock('\OCP\IUser');
|
||||
$expectedUser->expects($this->any())
|
||||
|
@ -56,41 +57,32 @@ class SessionTest extends \Test\TestCase {
|
|||
$manager = $this->getMockBuilder('\OC\User\Manager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$session->expects($this->at(1))
|
||||
->method('get')
|
||||
->with('app_password')
|
||||
->will($this->returnValue(null)); // No password set -> browser session
|
||||
$session->expects($this->once())
|
||||
->method('getId')
|
||||
->will($this->returnValue($sessionId));
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('getToken')
|
||||
->with($sessionId)
|
||||
->will($this->returnValue($token));
|
||||
$session->expects($this->at(2))
|
||||
->method('get')
|
||||
->with('last_login_check')
|
||||
->will($this->returnValue(null)); // No check has been run yet
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('getPassword')
|
||||
->with($token, $sessionId)
|
||||
->will($this->returnValue('password123'));
|
||||
->will($this->returnValue('passme'));
|
||||
$manager->expects($this->once())
|
||||
->method('checkPassword')
|
||||
->with('User123', 'password123')
|
||||
->with('User123', 'passme')
|
||||
->will($this->returnValue(true));
|
||||
$expectedUser->expects($this->once())
|
||||
->method('isEnabled')
|
||||
->will($this->returnValue(true));
|
||||
$session->expects($this->at(3))
|
||||
->method('set')
|
||||
->with('last_login_check', 10000);
|
||||
|
||||
$session->expects($this->at(4))
|
||||
->method('get')
|
||||
->with('last_token_update')
|
||||
->will($this->returnValue(null)); // No check run so far
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('updateToken')
|
||||
->method('updateTokenActivity')
|
||||
->with($token);
|
||||
$session->expects($this->at(5))
|
||||
->method('set')
|
||||
->with('last_token_update', $this->equalTo(10000));
|
||||
|
||||
$manager->expects($this->any())
|
||||
->method('get')
|
||||
|
@ -100,6 +92,7 @@ class SessionTest extends \Test\TestCase {
|
|||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
|
||||
$user = $userSession->getUser();
|
||||
$this->assertSame($expectedUser, $user);
|
||||
$this->assertSame(10000, $token->getLastCheck());
|
||||
}
|
||||
|
||||
public function isLoggedInData() {
|
||||
|
@ -155,6 +148,10 @@ class SessionTest extends \Test\TestCase {
|
|||
$session = $this->getMock('\OC\Session\Memory', array(), array(''));
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('getToken')
|
||||
->with('bar')
|
||||
->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
|
||||
$session->expects($this->exactly(2))
|
||||
->method('set')
|
||||
->with($this->callback(function ($key) {
|
||||
|
@ -219,6 +216,10 @@ class SessionTest extends \Test\TestCase {
|
|||
->method('set');
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('getToken')
|
||||
->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
|
||||
|
@ -252,11 +253,6 @@ class SessionTest extends \Test\TestCase {
|
|||
|
||||
public function testLoginInvalidPassword() {
|
||||
$session = $this->getMock('\OC\Session\Memory', array(), array(''));
|
||||
$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
|
||||
|
@ -268,10 +264,20 @@ class SessionTest extends \Test\TestCase {
|
|||
}
|
||||
}
|
||||
$manager = $this->getMock('\OC\User\Manager', $managerMethods, array());
|
||||
|
||||
$backend = $this->getMock('\Test\Util\User\Dummy');
|
||||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
|
||||
|
||||
$user = $this->getMock('\OC\User\User', array(), array('foo', $backend));
|
||||
|
||||
$session->expects($this->never())
|
||||
->method('set');
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('getToken')
|
||||
->with('bar')
|
||||
->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
|
||||
|
||||
$user->expects($this->never())
|
||||
->method('isEnabled');
|
||||
$user->expects($this->never())
|
||||
|
@ -282,27 +288,29 @@ class SessionTest extends \Test\TestCase {
|
|||
->with('foo', 'bar')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
|
||||
$userSession->login('foo', 'bar');
|
||||
}
|
||||
|
||||
public function testLoginNonExisting() {
|
||||
$session = $this->getMock('\OC\Session\Memory', array(), array(''));
|
||||
$manager = $this->getMock('\OC\User\Manager');
|
||||
$backend = $this->getMock('\Test\Util\User\Dummy');
|
||||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
|
||||
|
||||
$session->expects($this->never())
|
||||
->method('set');
|
||||
$session->expects($this->once())
|
||||
->method('regenerateId');
|
||||
|
||||
$manager = $this->getMock('\OC\User\Manager');
|
||||
|
||||
$backend = $this->getMock('\Test\Util\User\Dummy');
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('getToken')
|
||||
->with('bar')
|
||||
->will($this->throwException(new \OC\Authentication\Exceptions\InvalidTokenException()));
|
||||
|
||||
$manager->expects($this->once())
|
||||
->method('checkPassword')
|
||||
->with('foo', 'bar')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
|
||||
$userSession->login('foo', 'bar');
|
||||
}
|
||||
|
||||
|
@ -354,24 +362,14 @@ class SessionTest extends \Test\TestCase {
|
|||
->will($this->returnValue(true));
|
||||
$userSession->expects($this->once())
|
||||
->method('login')
|
||||
->with('john', 'doe')
|
||||
->with('john', 'I-AM-AN-APP-PASSWORD')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$userSession->expects($this->once())
|
||||
->method('supportsCookies')
|
||||
->with($request)
|
||||
->will($this->returnValue(true));
|
||||
$userSession->expects($this->once())
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('user123'));
|
||||
$userSession->expects($this->once())
|
||||
->method('createSessionToken')
|
||||
->with($request, 'user123', 'john', 'doe');
|
||||
|
||||
$this->assertTrue($userSession->logClientIn('john', 'doe', $request));
|
||||
$session->expects($this->once())
|
||||
->method('set')
|
||||
->with('app_password', 'I-AM-AN-APP-PASSWORD');
|
||||
|
||||
$this->assertTrue($userSession->logClientIn('john', 'I-AM-AN-APP-PASSWORD', $request));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -706,9 +704,15 @@ class SessionTest extends \Test\TestCase {
|
|||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$session = new Memory('');
|
||||
$token = $this->getMock('\OC\Authentication\Token\IToken');
|
||||
$token = new \OC\Authentication\Token\DefaultToken();
|
||||
$token->setLoginName('fritz');
|
||||
$token->setUid('fritz0');
|
||||
$token->setLastCheck(100); // Needs check
|
||||
$user = $this->getMock('\OCP\IUser');
|
||||
$userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->tokenProvider, $this->config);
|
||||
$userSession = $this->getMockBuilder('\OC\User\Session')
|
||||
->setMethods(['logout'])
|
||||
->setConstructorArgs([$manager, $session, $this->timeFactory, $this->tokenProvider, $this->config])
|
||||
->getMock();
|
||||
$request = $this->getMock('\OCP\IRequest');
|
||||
|
||||
$request->expects($this->once())
|
||||
|
@ -716,15 +720,12 @@ class SessionTest extends \Test\TestCase {
|
|||
->with('Authorization')
|
||||
->will($this->returnValue('token xxxxx'));
|
||||
$this->tokenProvider->expects($this->once())
|
||||
->method('validateToken')
|
||||
->method('getToken')
|
||||
->with('xxxxx')
|
||||
->will($this->returnValue($token));
|
||||
$token->expects($this->once())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('user123'));
|
||||
$manager->expects($this->once())
|
||||
->method('get')
|
||||
->with('user123')
|
||||
->with('fritz0')
|
||||
->will($this->returnValue($user));
|
||||
$user->expects($this->once())
|
||||
->method('isEnabled')
|
||||
|
@ -744,40 +745,40 @@ class SessionTest extends \Test\TestCase {
|
|||
->getMock();
|
||||
|
||||
$user = $this->getMock('\OCP\IUser');
|
||||
$token = $this->getMock('\OC\Authentication\Token\IToken');
|
||||
$token = new \OC\Authentication\Token\DefaultToken();
|
||||
$token->setLoginName('susan');
|
||||
$token->setLastCheck(20);
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('getId')
|
||||
->will($this->returnValue('sessionid'));
|
||||
->method('get')
|
||||
->with('app_password')
|
||||
->will($this->returnValue('APP-PASSWORD'));
|
||||
$tokenProvider->expects($this->once())
|
||||
->method('getToken')
|
||||
->with('sessionid')
|
||||
->with('APP-PASSWORD')
|
||||
->will($this->returnValue($token));
|
||||
$session->expects($this->once())
|
||||
->method('get')
|
||||
->with('last_login_check')
|
||||
->will($this->returnValue(1000));
|
||||
$timeFactory->expects($this->once())
|
||||
->method('getTime')
|
||||
->will($this->returnValue(5000));
|
||||
->will($this->returnValue(1000)); // more than 5min since last check
|
||||
$tokenProvider->expects($this->once())
|
||||
->method('getPassword')
|
||||
->with($token, 'sessionid')
|
||||
->with($token, 'APP-PASSWORD')
|
||||
->will($this->returnValue('123456'));
|
||||
$token->expects($this->once())
|
||||
->method('getLoginName')
|
||||
->will($this->returnValue('User5'));
|
||||
$userManager->expects($this->once())
|
||||
->method('checkPassword')
|
||||
->with('User5', '123456')
|
||||
->with('susan', '123456')
|
||||
->will($this->returnValue(true));
|
||||
$user->expects($this->once())
|
||||
->method('isEnabled')
|
||||
->will($this->returnValue(false));
|
||||
$tokenProvider->expects($this->once())
|
||||
->method('invalidateToken')
|
||||
->with('APP-PASSWORD');
|
||||
$userSession->expects($this->once())
|
||||
->method('logout');
|
||||
|
||||
$this->invokePrivate($userSession, 'validateSession', [$user]);
|
||||
$userSession->setUser($user);
|
||||
$this->invokePrivate($userSession, 'validateSession');
|
||||
}
|
||||
|
||||
public function testValidateSessionNoPassword() {
|
||||
|
@ -791,31 +792,31 @@ class SessionTest extends \Test\TestCase {
|
|||
->getMock();
|
||||
|
||||
$user = $this->getMock('\OCP\IUser');
|
||||
$token = $this->getMock('\OC\Authentication\Token\IToken');
|
||||
$token = new \OC\Authentication\Token\DefaultToken();
|
||||
$token->setLastCheck(20);
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('getId')
|
||||
->will($this->returnValue('sessionid'));
|
||||
$tokenProvider->expects($this->once())
|
||||
->method('getToken')
|
||||
->with('sessionid')
|
||||
->will($this->returnValue($token));
|
||||
$session->expects($this->once())
|
||||
->method('get')
|
||||
->with('last_login_check')
|
||||
->will($this->returnValue(1000));
|
||||
->with('app_password')
|
||||
->will($this->returnValue('APP-PASSWORD'));
|
||||
$tokenProvider->expects($this->once())
|
||||
->method('getToken')
|
||||
->with('APP-PASSWORD')
|
||||
->will($this->returnValue($token));
|
||||
$timeFactory->expects($this->once())
|
||||
->method('getTime')
|
||||
->will($this->returnValue(5000));
|
||||
->will($this->returnValue(1000)); // more than 5min since last check
|
||||
$tokenProvider->expects($this->once())
|
||||
->method('getPassword')
|
||||
->with($token, 'sessionid')
|
||||
->with($token, 'APP-PASSWORD')
|
||||
->will($this->throwException(new \OC\Authentication\Exceptions\PasswordlessTokenException()));
|
||||
$session->expects($this->once())
|
||||
->method('set')
|
||||
->with('last_login_check', 5000);
|
||||
$tokenProvider->expects($this->once())
|
||||
->method('updateToken')
|
||||
->with($token);
|
||||
|
||||
$this->invokePrivate($userSession, 'validateSession', [$user]);
|
||||
|
||||
$this->assertEquals(1000, $token->getLastCheck());
|
||||
}
|
||||
|
||||
public function testUpdateSessionTokenPassword() {
|
||||
|
|
|
@ -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, 1, 0, 8);
|
||||
$OC_Version = array(9, 1, 0, 9);
|
||||
|
||||
// The human readable string
|
||||
$OC_VersionString = '9.1.0 beta 2';
|
||||
|
|
Loading…
Reference in New Issue