Skip to content
Snippets Groups Projects
Unverified Commit ad10485c authored by Christoph Wurst's avatar Christoph Wurst
Browse files

when generating browser/device token, save the login name for later password checks

parent a0ccebfd
No related branches found
No related tags found
No related merge requests found
Showing
with 105 additions and 37 deletions
......@@ -105,7 +105,7 @@ class Auth extends AbstractBasic {
\OC_Util::setUpFS(); //login hooks may need early access to the filesystem
// TODO: do not allow basic auth if the user is 2FA enforced
if($this->userSession->login($username, $password)) {
$this->userSession->createSessionToken($this->request, $username, $password);
$this->userSession->createSessionToken($this->request, $this->userSession->getUser()->getUID(), $username, $password);
\OC_Util::setUpFS($this->userSession->getUser()->getUID());
$this->session->set(self::DAV_AUTHENTICATED, $this->userSession->getUser()->getUID());
$this->session->close();
......
......@@ -149,7 +149,7 @@ class Auth extends TestCase {
$user = $this->getMockBuilder('\OCP\IUser')
->disableOriginalConstructor()
->getMock();
$user->expects($this->exactly(3))
$user->expects($this->exactly(4))
->method('getUID')
->will($this->returnValue('MyTestUser'));
$this->userSession
......@@ -157,7 +157,7 @@ class Auth extends TestCase {
->method('isLoggedIn')
->will($this->returnValue(true));
$this->userSession
->expects($this->exactly(3))
->expects($this->exactly(4))
->method('getUser')
->will($this->returnValue($user));
$this->session
......@@ -173,7 +173,7 @@ class Auth extends TestCase {
$this->userSession
->expects($this->once())
->method('createSessionToken')
->with($this->request, 'MyTestUser', 'MyTestPassword');
->with($this->request, 'MyTestUser', 'MyTestUser', 'MyTestPassword');
$this->session
->expects($this->once())
->method('set')
......@@ -569,11 +569,11 @@ class Auth extends TestCase {
$user = $this->getMockBuilder('\OCP\IUser')
->disableOriginalConstructor()
->getMock();
$user->expects($this->exactly(3))
$user->expects($this->exactly(4))
->method('getUID')
->will($this->returnValue('MyTestUser'));
$this->userSession
->expects($this->exactly(3))
->expects($this->exactly(4))
->method('getUser')
->will($this->returnValue($user));
$response = $this->auth->check($server->httpRequest, $server->httpResponse);
......
......@@ -193,7 +193,7 @@ 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(), $password);
$this->userSession->createSessionToken($this->request, $loginResult->getUID(), $user, $password);
if ($this->twoFactorManager->isTwoFactorAuthenticated($loginResult)) {
$this->twoFactorManager->prepareTwoFactorLogin($loginResult);
......
......@@ -82,7 +82,7 @@ class TokenController extends Controller {
return $response;
}
$token = $this->secureRandom->generate(128);
$this->tokenProvider->generateToken($token, $loginResult->getUID(), $password, $name, IToken::PERMANENT_TOKEN);
$this->tokenProvider->generateToken($token, $loginResult->getUID(), $user, $password, $name, IToken::PERMANENT_TOKEN);
return [
'token' => $token,
];
......
......@@ -63,8 +63,8 @@ class TwoFactorChallengeController extends Controller {
}
/**
* @NoAdminRequired
* @NoCSRFRequired
* @PublicPage
*
* @return TemplateResponse
*/
......@@ -79,8 +79,8 @@ class TwoFactorChallengeController extends Controller {
}
/**
* @NoAdminRequired
* @NoCSRFRequired
* @PublicPage
* @UseSession
*
* @param string $challengeProviderId
......@@ -108,8 +108,8 @@ class TwoFactorChallengeController extends Controller {
}
/**
* @NoAdminRequired
* @NoCSRFRequired
* @PublicPage
* @UseSession
*
* @param string $challengeProviderId
......
......@@ -1072,6 +1072,14 @@
<length>64</length>
</field>
<field>
<name>login_name</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>64</length>
</field>
<field>
<name>password</name>
<type>clob</type>
......
......@@ -27,6 +27,8 @@ use OCP\AppFramework\Db\Entity;
/**
* @method void setId(int $id)
* @method void setUid(string $uid);
* @method void setLoginName(string $loginName)
* @method string getLoginName()
* @method void setPassword(string $password)
* @method void setName(string $name)
* @method string getName()
......@@ -44,6 +46,11 @@ class DefaultToken extends Entity implements IToken {
*/
protected $uid;
/**
* @var string login name used for generating the token
*/
protected $loginName;
/**
* @var string encrypted user password
*/
......@@ -76,7 +83,16 @@ class DefaultToken extends Entity implements IToken {
public function getUID() {
return $this->uid;
}
/**
* Get the login name used when generating the token
*
* @return string
*/
public function getLoginName() {
return parent::getLoginName();
}
/**
* Get the (encrypted) login password
*
......
......@@ -71,7 +71,7 @@ class DefaultTokenMapper extends Mapper {
public function getToken($token) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$result = $qb->select('id', 'uid', 'password', 'name', 'type', 'token', 'last_activity')
$result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity')
->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', 'password', 'name', 'type', 'token', 'last_activity')
$qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity')
->from('authtoken')
->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())))
->setMaxResults(1000);
......
......@@ -68,14 +68,16 @@ class DefaultTokenProvider implements IProvider {
*
* @param string $token
* @param string $uid
* @param string $loginName
* @param string $password
* @param string $name
* @param int $type token type
* @return DefaultToken
* @return IToken
*/
public function generateToken($token, $uid, $password, $name, $type = IToken::TEMPORARY_TOKEN) {
public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN) {
$dbToken = new DefaultToken();
$dbToken->setUid($uid);
$dbToken->setLoginName($loginName);
$dbToken->setPassword($this->encryptPassword($password, $token));
$dbToken->setName($name);
$dbToken->setToken($this->hashToken($token));
......
......@@ -32,12 +32,13 @@ interface IProvider {
*
* @param string $token
* @param string $uid
* @param string $loginName
* @param string $password
* @param string $name
* @param int $type token type
* @return IToken
*/
public function generateToken($token, $uid, $password, $name, $type = IToken::TEMPORARY_TOKEN);
public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN);
/**
* Get a token by token id
......
......@@ -43,6 +43,13 @@ interface IToken extends JsonSerializable {
*/
public function getUID();
/**
* Get the login name used when generating the token
*
* @return string
*/
public function getLoginName();
/**
* Get the (encrypted) login password
*
......
......@@ -372,7 +372,7 @@ class Setup {
$defaultTokenProvider = \OC::$server->query('OC\Authentication\Token\DefaultTokenProvider');
$userSession->setTokenProvider($defaultTokenProvider);
$userSession->login($username, $password);
$userSession->createSessionToken($request, $username, $password);
$userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password);
//guess what this does
Installer::installShippedApps();
......
......@@ -219,7 +219,7 @@ class Session implements IUserSession, Emitter {
return;
}
if ($this->manager->checkPassword($user->getUID(), $pwd) === false
if ($this->manager->checkPassword($token->getLoginName(), $pwd) === false
|| !$user->isEnabled()) {
// Password has changed or user was disabled -> log user out
$this->logout();
......@@ -388,10 +388,11 @@ class Session implements IUserSession, Emitter {
*
* @param IRequest $request
* @param string $uid user UID
* @param string $loginName login name
* @param string $password
* @return boolean
*/
public function createSessionToken(IRequest $request, $uid, $password) {
public function createSessionToken(IRequest $request, $uid, $loginName, $password) {
if (is_null($this->manager->get($uid))) {
// User does not exist
return false;
......@@ -399,7 +400,7 @@ class Session implements IUserSession, Emitter {
$name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser';
try {
$sessionId = $this->session->getId();
$this->tokenProvider->generateToken($sessionId, $uid, $password, $name);
$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $password, $name);
} catch (SessionNotAvailableException $ex) {
}
......
......@@ -101,6 +101,7 @@ class AuthSettingsController extends Controller {
try {
$sessionToken = $this->tokenProvider->getToken($sessionId);
$loginName = $sessionToken->getLoginName();
$password = $this->tokenProvider->getPassword($sessionToken, $sessionId);
} catch (InvalidTokenException $ex) {
$resp = new JSONResponse();
......@@ -109,7 +110,7 @@ class AuthSettingsController extends Controller {
}
$token = $this->generateRandomDeviceToken();
$deviceToken = $this->tokenProvider->generateToken($token, $this->uid, $password, $name, IToken::PERMANENT_TOKEN);
$deviceToken = $this->tokenProvider->generateToken($token, $this->uid, $loginName, $password, $name, IToken::PERMANENT_TOKEN);
return [
'token' => $token,
......
......@@ -303,9 +303,12 @@ class LoginControllerTest extends TestCase {
$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(), $password);
->with($this->request, $user->getUID(), $user, $password);
$this->twoFactorManager->expects($this->once())
->method('isTwoFactorAuthenticated')
->with($user)
......@@ -330,11 +333,11 @@ class LoginControllerTest extends TestCase {
$this->userManager->expects($this->once())
->method('checkPassword')
->with('jane', $password)
->with('Jane', $password)
->will($this->returnValue($user));
$this->userSession->expects($this->once())
->method('createSessionToken')
->with($this->request, $user->getUID(), $password);
->with($this->request, $user->getUID(), 'Jane', $password);
$this->userSession->expects($this->once())
->method('isLoggedIn')
->with()
......@@ -345,20 +348,26 @@ class LoginControllerTest extends TestCase {
->will($this->returnValue($redirectUrl));
$expected = new \OCP\AppFramework\Http\RedirectResponse(urldecode($redirectUrl));
$this->assertEquals($expected, $this->loginController->tryLogin($user->getUID(), $password, $originalUrl));
$this->assertEquals($expected, $this->loginController->tryLogin('Jane', $password, $originalUrl));
}
public function testLoginWithTwoFactorEnforced() {
$user = $this->getMock('\OCP\IUser');
$user->expects($this->any())
->method('getUID')
->will($this->returnValue('john'));
$password = 'secret';
$challengeUrl = 'challenge/url';
$this->userManager->expects($this->once())
->method('checkPassword')
->will($this->returnValue($user));
$this->userSession->expects($this->once())
->method('login')
->with('john@doe.com', $password);
$this->userSession->expects($this->once())
->method('createSessionToken')
->with($this->request, $user->getUID(), $password);
->with($this->request, $user->getUID(), 'john@doe.com', $password);
$this->twoFactorManager->expects($this->once())
->method('isTwoFactorAuthenticated')
->with($user)
......@@ -372,7 +381,7 @@ class LoginControllerTest extends TestCase {
->will($this->returnValue($challengeUrl));
$expected = new \OCP\AppFramework\Http\RedirectResponse($challengeUrl);
$this->assertEquals($expected, $this->loginController->tryLogin($user, $password, null));
$this->assertEquals($expected, $this->loginController->tryLogin('john@doe.com', $password, null));
}
}
......@@ -75,14 +75,21 @@ class TokenControllerTest extends TestCase {
}
public function testWithValidCredentials() {
$user = $this->getMock('\OCP\IUser');
$this->userManager->expects($this->once())
->method('checkPassword')
->with('john', '123456')
->will($this->returnValue(true));
->will($this->returnValue($user));
$user->expects($this->once())
->method('getUID')
->will($this->returnValue('john'));
$this->secureRandom->expects($this->once())
->method('generate')
->with(128)
->will($this->returnValue('verysecurerandomtoken'));
$this->tokenProvider->expects($this->once())
->method('generateToken')
->with('verysecurerandomtoken', 'john', 'john', '123456', 'unknown client', \OC\Authentication\Token\IToken::PERMANENT_TOKEN);
$expected = [
'token' => 'verysecurerandomtoken'
];
......
......@@ -57,6 +57,7 @@ class DefaultTokenMapperTest extends TestCase {
$qb->delete('authtoken')->execute();
$qb->insert('authtoken')->values([
'uid' => $qb->createNamedParameter('user1'),
'login_name' => $qb->createNamedParameter('User1'),
'password' => $qb->createNamedParameter('a75c7116460c082912d8f6860a850904|3nz5qbG1nNSLLi6V|c55365a0e54cfdfac4a175bcf11a7612aea74492277bba6e5d96a24497fa9272488787cb2f3ad34d8b9b8060934fce02f008d371df3ff3848f4aa61944851ff0'),
'name' => $qb->createNamedParameter('Firefox on Linux'),
'token' => $qb->createNamedParameter('9c5a2e661482b65597408a6bb6c4a3d1af36337381872ac56e445a06cdb7fea2b1039db707545c11027a4966919918b19d875a8b774840b18c6cbb7ae56fe206'),
......@@ -65,6 +66,7 @@ class DefaultTokenMapperTest extends TestCase {
])->execute();
$qb->insert('authtoken')->values([
'uid' => $qb->createNamedParameter('user2'),
'login_name' => $qb->createNamedParameter('User2'),
'password' => $qb->createNamedParameter('971a337057853344700bbeccf836519f|UwOQwyb34sJHtqPV|036d4890f8c21d17bbc7b88072d8ef049a5c832a38e97f3e3d5f9186e896c2593aee16883f617322fa242728d0236ff32d163caeb4bd45e14ca002c57a88665f'),
'name' => $qb->createNamedParameter('Firefox on Android'),
'token' => $qb->createNamedParameter('1504445f1524fc801035448a95681a9378ba2e83930c814546c56e5d6ebde221198792fd900c88ed5ead0555780dad1ebce3370d7e154941cd5de87eb419899b'),
......@@ -73,6 +75,7 @@ class DefaultTokenMapperTest extends TestCase {
])->execute();
$qb->insert('authtoken')->values([
'uid' => $qb->createNamedParameter('user1'),
'login_name' => $qb->createNamedParameter('User1'),
'password' => $qb->createNamedParameter('063de945d6f6b26862d9b6f40652f2d5|DZ/z520tfdXPtd0T|395f6b89be8d9d605e409e20b9d9abe477fde1be38a3223f9e508f979bf906e50d9eaa4dca983ca4fb22a241eb696c3f98654e7775f78c4caf13108f98642b53'),
'name' => $qb->createNamedParameter('Iceweasel on Linux'),
'token' => $qb->createNamedParameter('47af8697ba590fb82579b5f1b3b6e8066773a62100abbe0db09a289a62f5d980dc300fa3d98b01d7228468d1ab05c1aa14c8d14bd5b6eee9cdf1ac14864680c3'),
......@@ -118,6 +121,7 @@ class DefaultTokenMapperTest extends TestCase {
$token = '1504445f1524fc801035448a95681a9378ba2e83930c814546c56e5d6ebde221198792fd900c88ed5ead0555780dad1ebce3370d7e154941cd5de87eb419899b';
$token = new DefaultToken();
$token->setUid('user2');
$token->setLoginName('User2');
$token->setPassword('971a337057853344700bbeccf836519f|UwOQwyb34sJHtqPV|036d4890f8c21d17bbc7b88072d8ef049a5c832a38e97f3e3d5f9186e896c2593aee16883f617322fa242728d0236ff32d163caeb4bd45e14ca002c57a88665f');
$token->setName('Firefox on Android');
$token->setToken('1504445f1524fc801035448a95681a9378ba2e83930c814546c56e5d6ebde221198792fd900c88ed5ead0555780dad1ebce3370d7e154941cd5de87eb419899b');
......
......@@ -61,6 +61,7 @@ class DefaultTokenProviderTest extends TestCase {
public function testGenerateToken() {
$token = 'token';
$uid = 'user';
$user = 'User';
$password = 'passme';
$name = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
. 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'
......@@ -70,6 +71,7 @@ class DefaultTokenProviderTest extends TestCase {
$toInsert = new DefaultToken();
$toInsert->setUid($uid);
$toInsert->setLoginName($user);
$toInsert->setPassword('encryptedpassword');
$toInsert->setName($name);
$toInsert->setToken(hash('sha512', $token . '1f4h9s'));
......@@ -88,7 +90,7 @@ class DefaultTokenProviderTest extends TestCase {
->method('insert')
->with($this->equalTo($toInsert));
$actual = $this->tokenProvider->generateToken($token, $uid, $password, $name, $type);
$actual = $this->tokenProvider->generateToken($token, $uid, $user, $password, $name, $type);
$this->assertEquals($toInsert, $actual);
}
......
......@@ -38,8 +38,12 @@ class SessionTest extends \Test\TestCase {
public function testGetUser() {
$token = new \OC\Authentication\Token\DefaultToken();
$token->setLoginName('User123');
$expectedUser = new User('foo', null);
$expectedUser = $this->getMock('\OCP\IUser');
$expectedUser->expects($this->any())
->method('getUID')
->will($this->returnValue('user123'));
$session = $this->getMock('\OC\Session\Memory', array(), array(''));
$session->expects($this->at(0))
->method('get')
......@@ -66,7 +70,10 @@ class SessionTest extends \Test\TestCase {
->will($this->returnValue('password123'));
$manager->expects($this->once())
->method('checkPassword')
->with($expectedUser->getUID(), 'password123')
->with('User123', 'password123')
->will($this->returnValue(true));
$expectedUser->expects($this->once())
->method('isEnabled')
->will($this->returnValue(true));
$session->expects($this->at(3))
->method('set')
......@@ -540,12 +547,12 @@ class SessionTest extends \Test\TestCase {
->method('getPassword')
->with($token, 'sessionid')
->will($this->returnValue('123456'));
$user->expects($this->once())
->method('getUID')
->will($this->returnValue('user5'));
$token->expects($this->once())
->method('getLoginName')
->will($this->returnValue('User5'));
$userManager->expects($this->once())
->method('checkPassword')
->with('user5', '123456')
->with('User5', '123456')
->will($this->returnValue(true));
$user->expects($this->once())
->method('isEnabled')
......
......@@ -89,6 +89,9 @@ class AuthSettingsControllerTest extends TestCase {
->method('getPassword')
->with($sessionToken, 'sessionid')
->will($this->returnValue($password));
$sessionToken->expects($this->once())
->method('getLoginName')
->will($this->returnValue('User13'));
$this->secureRandom->expects($this->exactly(4))
->method('generate')
......@@ -98,7 +101,7 @@ class AuthSettingsControllerTest extends TestCase {
$this->tokenProvider->expects($this->once())
->method('generateToken')
->with($newToken, $this->uid, $password, $name, IToken::PERMANENT_TOKEN)
->with($newToken, $this->uid, 'User13', $password, $name, IToken::PERMANENT_TOKEN)
->will($this->returnValue($deviceToken));
$expected = [
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment