use login hook credentials as fallback
If no session token is available, we can use the credentials provided by the login hook. Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
parent
e4abb9cb6e
commit
6f74ecd94a
|
@ -32,27 +32,17 @@ use OCP\Authentication\Exceptions\CredentialsUnavailableException;
|
||||||
use OCP\Authentication\LoginCredentials\IStore as CredentialsStore;
|
use OCP\Authentication\LoginCredentials\IStore as CredentialsStore;
|
||||||
use OCP\Files\Storage;
|
use OCP\Files\Storage;
|
||||||
use OCP\IL10N;
|
use OCP\IL10N;
|
||||||
use OCP\ISession;
|
|
||||||
use OCP\IUser;
|
use OCP\IUser;
|
||||||
use OCP\Security\ICrypto;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Username and password from login credentials, saved in session
|
* Username and password from login credentials, saved in session
|
||||||
*/
|
*/
|
||||||
class SessionCredentials extends AuthMechanism {
|
class SessionCredentials extends AuthMechanism {
|
||||||
|
|
||||||
/** @var ISession */
|
|
||||||
protected $session;
|
|
||||||
|
|
||||||
/** @var ICrypto */
|
|
||||||
protected $crypto;
|
|
||||||
|
|
||||||
/** @var CredentialsStore */
|
/** @var CredentialsStore */
|
||||||
private $credentialsStore;
|
private $credentialsStore;
|
||||||
|
|
||||||
public function __construct(IL10N $l, ISession $session, ICrypto $crypto, CredentialsStore $credentialsStore) {
|
public function __construct(IL10N $l, CredentialsStore $credentialsStore) {
|
||||||
$this->session = $session;
|
|
||||||
$this->crypto = $crypto;
|
|
||||||
$this->credentialsStore = $credentialsStore;
|
$this->credentialsStore = $credentialsStore;
|
||||||
|
|
||||||
$this->setIdentifier('password::sessioncredentials')
|
$this->setIdentifier('password::sessioncredentials')
|
||||||
|
|
|
@ -33,6 +33,7 @@ use OCP\Authentication\LoginCredentials\IStore;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
use OCP\ISession;
|
use OCP\ISession;
|
||||||
use OCP\Session\Exceptions\SessionNotAvailableException;
|
use OCP\Session\Exceptions\SessionNotAvailableException;
|
||||||
|
use OCP\Util;
|
||||||
|
|
||||||
class Store implements IStore {
|
class Store implements IStore {
|
||||||
|
|
||||||
|
@ -54,6 +55,17 @@ class Store implements IStore {
|
||||||
$this->session = $session;
|
$this->session = $session;
|
||||||
$this->tokenProvider = $tokenProvider;
|
$this->tokenProvider = $tokenProvider;
|
||||||
$this->logger = $logger;
|
$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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,6 +84,7 @@ class Store implements IStore {
|
||||||
* @throws CredentialsUnavailableException
|
* @throws CredentialsUnavailableException
|
||||||
*/
|
*/
|
||||||
public function getLoginCredentials() {
|
public function getLoginCredentials() {
|
||||||
|
$trySession = false;
|
||||||
try {
|
try {
|
||||||
$sessionId = $this->session->getId();
|
$sessionId = $this->session->getId();
|
||||||
$token = $this->tokenProvider->getToken($sessionId);
|
$token = $this->tokenProvider->getToken($sessionId);
|
||||||
|
@ -85,9 +98,17 @@ class Store implements IStore {
|
||||||
$this->logger->debug('could not get login credentials because session is unavailable', ['app' => 'core']);
|
$this->logger->debug('could not get login credentials because session is unavailable', ['app' => 'core']);
|
||||||
} catch (InvalidTokenException $ex) {
|
} catch (InvalidTokenException $ex) {
|
||||||
$this->logger->debug('could not get login credentials because the token is invalid', ['app' => 'core']);
|
$this->logger->debug('could not get login credentials because the token is invalid', ['app' => 'core']);
|
||||||
|
$trySession = true;
|
||||||
} catch (PasswordlessTokenException $ex) {
|
} catch (PasswordlessTokenException $ex) {
|
||||||
$this->logger->debug('could not get login credentials because the token has no password', ['app' => 'core']);
|
$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.
|
// If we reach this line, an exception was thrown.
|
||||||
throw new CredentialsUnavailableException();
|
throw new CredentialsUnavailableException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ use OCP\Authentication\Exceptions\CredentialsUnavailableException;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
use OCP\ISession;
|
use OCP\ISession;
|
||||||
use OCP\Session\Exceptions\SessionNotAvailableException;
|
use OCP\Session\Exceptions\SessionNotAvailableException;
|
||||||
|
use PHPUnit_Framework_MockObject_MockObject;
|
||||||
use Test\TestCase;
|
use Test\TestCase;
|
||||||
|
|
||||||
class StoreTest extends TestCase {
|
class StoreTest extends TestCase {
|
||||||
|
@ -60,6 +61,26 @@ class StoreTest extends TestCase {
|
||||||
$this->store = new Store($this->session, $this->tokenProvider, $this->logger);
|
$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() {
|
public function testGetLoginCredentials() {
|
||||||
$uid = 'uid';
|
$uid = 'uid';
|
||||||
$user = 'user123';
|
$user = 'user123';
|
||||||
|
@ -67,21 +88,21 @@ class StoreTest extends TestCase {
|
||||||
$token = $this->createMock(IToken::class);
|
$token = $this->createMock(IToken::class);
|
||||||
$this->session->expects($this->once())
|
$this->session->expects($this->once())
|
||||||
->method('getId')
|
->method('getId')
|
||||||
->will($this->returnValue('sess2233'));
|
->willReturn('sess2233');
|
||||||
$this->tokenProvider->expects($this->once())
|
$this->tokenProvider->expects($this->once())
|
||||||
->method('getToken')
|
->method('getToken')
|
||||||
->with('sess2233')
|
->with('sess2233')
|
||||||
->will($this->returnValue($token));
|
->willReturn($token);
|
||||||
$token->expects($this->once())
|
$token->expects($this->once())
|
||||||
->method('getUID')
|
->method('getUID')
|
||||||
->will($this->returnValue($uid));
|
->willReturn($uid);
|
||||||
$token->expects($this->once())
|
$token->expects($this->once())
|
||||||
->method('getLoginName')
|
->method('getLoginName')
|
||||||
->will($this->returnValue($user));
|
->willReturn($user);
|
||||||
$this->tokenProvider->expects($this->once())
|
$this->tokenProvider->expects($this->once())
|
||||||
->method('getPassword')
|
->method('getPassword')
|
||||||
->with($token, 'sess2233')
|
->with($token, 'sess2233')
|
||||||
->will($this->returnValue($password));
|
->willReturn($password);
|
||||||
$expected = new Credentials($uid, $user, $password);
|
$expected = new Credentials($uid, $user, $password);
|
||||||
|
|
||||||
$creds = $this->store->getLoginCredentials();
|
$creds = $this->store->getLoginCredentials();
|
||||||
|
@ -101,7 +122,7 @@ class StoreTest extends TestCase {
|
||||||
public function testGetLoginCredentialsInvalidToken() {
|
public function testGetLoginCredentialsInvalidToken() {
|
||||||
$this->session->expects($this->once())
|
$this->session->expects($this->once())
|
||||||
->method('getId')
|
->method('getId')
|
||||||
->will($this->returnValue('sess2233'));
|
->willReturn('sess2233');
|
||||||
$this->tokenProvider->expects($this->once())
|
$this->tokenProvider->expects($this->once())
|
||||||
->method('getToken')
|
->method('getToken')
|
||||||
->with('sess2233')
|
->with('sess2233')
|
||||||
|
@ -110,11 +131,37 @@ class StoreTest extends TestCase {
|
||||||
|
|
||||||
$this->store->getLoginCredentials();
|
$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() {
|
public function testGetLoginCredentialsPasswordlessToken() {
|
||||||
$this->session->expects($this->once())
|
$this->session->expects($this->once())
|
||||||
->method('getId')
|
->method('getId')
|
||||||
->will($this->returnValue('sess2233'));
|
->willReturn('sess2233');
|
||||||
$this->tokenProvider->expects($this->once())
|
$this->tokenProvider->expects($this->once())
|
||||||
->method('getToken')
|
->method('getToken')
|
||||||
->with('sess2233')
|
->with('sess2233')
|
||||||
|
|
Loading…
Reference in New Issue