Skip to content

Commit

Permalink
use login hook credentials as fallback
Browse files Browse the repository at this point in the history
If no session token is available, we can use the credentials provided
by the login hook.

Signed-off-by: Christoph Wurst <[email protected]>
  • Loading branch information
ChristophWurst committed Jan 2, 2017
1 parent f21c2db commit c10bfe2
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 19 deletions.
12 changes: 1 addition & 11 deletions apps/files_external/lib/Lib/Auth/Password/SessionCredentials.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,17 @@
use OCP\Authentication\LoginCredentials\IStore as CredentialsStore;
use OCP\Files\Storage;
use OCP\IL10N;
use OCP\ISession;
use OCP\IUser;
use OCP\Security\ICrypto;

/**
* Username and password from login credentials, saved in session
*/
class SessionCredentials extends AuthMechanism {

/** @var ISession */
protected $session;

/** @var ICrypto */
protected $crypto;

/** @var CredentialsStore */
private $credentialsStore;

public function __construct(IL10N $l, ISession $session, ICrypto $crypto, CredentialsStore $credentialsStore) {
$this->session = $session;
$this->crypto = $crypto;
public function __construct(IL10N $l, CredentialsStore $credentialsStore) {
$this->credentialsStore = $credentialsStore;

$this->setIdentifier('password::sessioncredentials')
Expand Down
21 changes: 21 additions & 0 deletions lib/private/Authentication/LoginCredentials/Store.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use OCP\ILogger;
use OCP\ISession;
use OCP\Session\Exceptions\SessionNotAvailableException;
use OCP\Util;

class Store implements IStore {

Expand All @@ -54,6 +55,17 @@ public function __construct(ISession $session, IProvider $tokenProvider, ILogger
$this->session = $session;
$this->tokenProvider = $tokenProvider;
$this->logger = $logger;

Util::connectHook('OC_User', 'post_login', $this, 'authenticate');
}

/**
* Hook listener on post login
*
* @param array $params
*/
public function authenticate(array $params) {
$this->session->set('login_credentials', json_encode($params));
}

/**
Expand All @@ -72,6 +84,7 @@ public function setSession(ISession $session) {
* @throws CredentialsUnavailableException
*/
public function getLoginCredentials() {
$trySession = false;
try {
$sessionId = $this->session->getId();
$token = $this->tokenProvider->getToken($sessionId);
Expand All @@ -85,9 +98,17 @@ public function getLoginCredentials() {
$this->logger->debug('could not get login credentials because session is unavailable', ['app' => 'core']);
} catch (InvalidTokenException $ex) {
$this->logger->debug('could not get login credentials because the token is invalid', ['app' => 'core']);
$trySession = true;
} catch (PasswordlessTokenException $ex) {
$this->logger->debug('could not get login credentials because the token has no password', ['app' => 'core']);
$trySession = true;
}

if ($trySession && $this->session->exists('login_credentials')) {
$creds = json_decode($this->session->get('login_credentials'));
return new Credentials($creds->uid, $creds->uid, $creds->password);
}

// If we reach this line, an exception was thrown.
throw new CredentialsUnavailableException();
}
Expand Down
63 changes: 55 additions & 8 deletions tests/lib/Authentication/LoginCredentials/StoreTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use OCP\ILogger;
use OCP\ISession;
use OCP\Session\Exceptions\SessionNotAvailableException;
use PHPUnit_Framework_MockObject_MockObject;
use Test\TestCase;

class StoreTest extends TestCase {
Expand All @@ -60,28 +61,48 @@ protected function setUp() {
$this->store = new Store($this->session, $this->tokenProvider, $this->logger);
}

public function testAuthenticate() {
$params = [
'run' => true,
'uid' => 'user123',
'password' => 123456,
];

$this->session->expects($this->once())
->method('set')
->with($this->equalTo('login_credentials'), $this->equalTo(json_encode($params)));

$this->store->authenticate($params);
}

public function testSetSession() {
$session = $this->createMock(ISession::class);

$this->store->setSession($session);
}

public function testGetLoginCredentials() {
$uid = 'uid';
$user = 'user123';
$password = 'passme';
$token = $this->createMock(IToken::class);
$this->session->expects($this->once())
->method('getId')
->will($this->returnValue('sess2233'));
->willReturn('sess2233');
$this->tokenProvider->expects($this->once())
->method('getToken')
->with('sess2233')
->will($this->returnValue($token));
->willReturn($token);
$token->expects($this->once())
->method('getUID')
->will($this->returnValue($uid));
->willReturn($uid);
$token->expects($this->once())
->method('getLoginName')
->will($this->returnValue($user));
->willReturn($user);
$this->tokenProvider->expects($this->once())
->method('getPassword')
->with($token, 'sess2233')
->will($this->returnValue($password));
->willReturn($password);
$expected = new Credentials($uid, $user, $password);

$creds = $this->store->getLoginCredentials();
Expand All @@ -101,7 +122,7 @@ public function testGetLoginCredentialsSessionNotAvailable() {
public function testGetLoginCredentialsInvalidToken() {
$this->session->expects($this->once())
->method('getId')
->will($this->returnValue('sess2233'));
->willReturn('sess2233');
$this->tokenProvider->expects($this->once())
->method('getToken')
->with('sess2233')
Expand All @@ -110,11 +131,37 @@ public function testGetLoginCredentialsInvalidToken() {

$this->store->getLoginCredentials();
}


public function testGetLoginCredentialsInvalidTokenLoginCredentials() {
$uid = 'user987';
$password = '7389374';

$this->session->expects($this->once())
->method('getId')
->willReturn('sess2233');
$this->tokenProvider->expects($this->once())
->method('getToken')
->with('sess2233')
->will($this->throwException(new InvalidTokenException()));
$this->session->expects($this->once())
->method('exists')
->with($this->equalTo('login_credentials'))
->willReturn(true);
$this->session->expects($this->once())
->method('get')
->with($this->equalTo('login_credentials'))
->willReturn('{"run":true,"uid":"user987","password":"7389374"}');
$expected = new Credentials('user987', 'user987', '7389374');

$actual = $this->store->getLoginCredentials();

$this->assertEquals($expected, $actual);
}

public function testGetLoginCredentialsPasswordlessToken() {
$this->session->expects($this->once())
->method('getId')
->will($this->returnValue('sess2233'));
->willReturn('sess2233');
$this->tokenProvider->expects($this->once())
->method('getToken')
->with('sess2233')
Expand Down

0 comments on commit c10bfe2

Please sign in to comment.