Merge pull request #20010 from owncloud/add-tests-auth-plugin
Add tests for Sabre Auth plugin + make getCurrentUser compatible
This commit is contained in:
commit
9a7a45bc37
3 changed files with 399 additions and 21 deletions
|
@ -44,7 +44,10 @@ $serverFactory = new \OCA\DAV\Connector\Sabre\ServerFactory(
|
|||
);
|
||||
|
||||
// Backends
|
||||
$authBackend = new \OCA\DAV\Connector\Sabre\Auth();
|
||||
$authBackend = new \OCA\DAV\Connector\Sabre\Auth(
|
||||
\OC::$server->getSession(),
|
||||
\OC::$server->getUserSession()
|
||||
);
|
||||
$requestUri = \OC::$server->getRequest()->getRequestUri();
|
||||
|
||||
$server = $serverFactory->createServer($baseuri, $requestUri, $authBackend, function() {
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
namespace OCA\DAV\Connector\Sabre;
|
||||
|
||||
use Exception;
|
||||
use OCP\ISession;
|
||||
use OCP\IUserSession;
|
||||
use Sabre\DAV\Auth\Backend\AbstractBasic;
|
||||
use Sabre\DAV\Exception\NotAuthenticated;
|
||||
use Sabre\DAV\Exception\ServiceUnavailable;
|
||||
|
@ -37,6 +39,21 @@ use Sabre\DAV\Exception\ServiceUnavailable;
|
|||
class Auth extends AbstractBasic {
|
||||
const DAV_AUTHENTICATED = 'AUTHENTICATED_TO_DAV_BACKEND';
|
||||
|
||||
/** @var ISession */
|
||||
private $session;
|
||||
/** @var IUserSession */
|
||||
private $userSession;
|
||||
|
||||
/**
|
||||
* @param ISession $session
|
||||
* @param IUserSession $userSession
|
||||
*/
|
||||
public function __construct(ISession $session,
|
||||
IUserSession $userSession) {
|
||||
$this->session = $session;
|
||||
$this->userSession = $userSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user has initially authenticated via DAV
|
||||
*
|
||||
|
@ -49,8 +66,8 @@ class Auth extends AbstractBasic {
|
|||
* @return bool
|
||||
*/
|
||||
protected function isDavAuthenticated($username) {
|
||||
return !is_null(\OC::$server->getSession()->get(self::DAV_AUTHENTICATED)) &&
|
||||
\OC::$server->getSession()->get(self::DAV_AUTHENTICATED) === $username;
|
||||
return !is_null($this->session->get(self::DAV_AUTHENTICATED)) &&
|
||||
$this->session->get(self::DAV_AUTHENTICATED) === $username;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,24 +81,21 @@ class Auth extends AbstractBasic {
|
|||
* @return bool
|
||||
*/
|
||||
protected function validateUserPass($username, $password) {
|
||||
if (\OC_User::isLoggedIn() &&
|
||||
$this->isDavAuthenticated(\OC_User::getUser())
|
||||
if ($this->userSession->isLoggedIn() &&
|
||||
$this->isDavAuthenticated($this->userSession->getUser()->getUID())
|
||||
) {
|
||||
\OC_Util::setupFS(\OC_User::getUser());
|
||||
\OC::$server->getSession()->close();
|
||||
\OC_Util::setupFS($this->userSession->getUser()->getUID());
|
||||
$this->session->close();
|
||||
return true;
|
||||
} else {
|
||||
\OC_Util::setUpFS(); //login hooks may need early access to the filesystem
|
||||
if(\OC_User::login($username, $password)) {
|
||||
// make sure we use ownCloud's internal username here
|
||||
// and not the HTTP auth supplied one, see issue #14048
|
||||
$ocUser = \OC_User::getUser();
|
||||
\OC_Util::setUpFS($ocUser);
|
||||
\OC::$server->getSession()->set(self::DAV_AUTHENTICATED, $ocUser);
|
||||
\OC::$server->getSession()->close();
|
||||
if($this->userSession->login($username, $password)) {
|
||||
\OC_Util::setUpFS($this->userSession->getUser()->getUID());
|
||||
$this->session->set(self::DAV_AUTHENTICATED, $this->userSession->getUser()->getUID());
|
||||
$this->session->close();
|
||||
return true;
|
||||
} else {
|
||||
\OC::$server->getSession()->close();
|
||||
$this->session->close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -95,10 +109,15 @@ class Auth extends AbstractBasic {
|
|||
* @return string|null
|
||||
*/
|
||||
public function getCurrentUser() {
|
||||
$user = \OC_User::getUser();
|
||||
if($user && $this->isDavAuthenticated($user)) {
|
||||
$user = $this->userSession->getUser() ? $this->userSession->getUser()->getUID() : null;
|
||||
if($user !== null && $this->isDavAuthenticated($user)) {
|
||||
return $user;
|
||||
}
|
||||
|
||||
if($user !== null && is_null($this->session->get(self::DAV_AUTHENTICATED))) {
|
||||
return $user;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -114,9 +133,9 @@ class Auth extends AbstractBasic {
|
|||
* @param string $realm
|
||||
* @return bool
|
||||
* @throws ServiceUnavailable
|
||||
* @throws NotAuthenticated
|
||||
*/
|
||||
public function authenticate(\Sabre\DAV\Server $server, $realm) {
|
||||
|
||||
try {
|
||||
$result = $this->auth($server, $realm);
|
||||
return $result;
|
||||
|
@ -136,12 +155,12 @@ class Auth extends AbstractBasic {
|
|||
*/
|
||||
private function auth(\Sabre\DAV\Server $server, $realm) {
|
||||
if (\OC_User::handleApacheAuth() ||
|
||||
(\OC_User::isLoggedIn() && is_null(\OC::$server->getSession()->get(self::DAV_AUTHENTICATED)))
|
||||
($this->userSession->isLoggedIn() && is_null($this->session->get(self::DAV_AUTHENTICATED)))
|
||||
) {
|
||||
$user = \OC_User::getUser();
|
||||
$user = $this->userSession->getUser()->getUID();
|
||||
\OC_Util::setupFS($user);
|
||||
$this->currentUser = $user;
|
||||
\OC::$server->getSession()->close();
|
||||
$this->session->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
356
apps/dav/tests/unit/connector/sabre/auth.php
Normal file
356
apps/dav/tests/unit/connector/sabre/auth.php
Normal file
|
@ -0,0 +1,356 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2015, ownCloud, Inc.
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
namespace Tests\Connector\Sabre;
|
||||
|
||||
use Test\TestCase;
|
||||
use OCP\ISession;
|
||||
use OCP\IUserSession;
|
||||
|
||||
/**
|
||||
* Class Auth
|
||||
*
|
||||
* @package OCA\DAV\Connector\Sabre
|
||||
*/
|
||||
class Auth extends TestCase {
|
||||
/** @var ISession */
|
||||
private $session;
|
||||
/** @var \OCA\DAV\Connector\Sabre\Auth */
|
||||
private $auth;
|
||||
/** @var IUserSession */
|
||||
private $userSession;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->session = $this->getMockBuilder('\OCP\ISession')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->userSession = $this->getMockBuilder('\OCP\IUserSession')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->auth = new \OCA\DAV\Connector\Sabre\Auth($this->session, $this->userSession);
|
||||
}
|
||||
|
||||
public function testIsDavAuthenticatedWithoutDavSession() {
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
|
||||
}
|
||||
|
||||
public function testIsDavAuthenticatedWithWrongDavSession() {
|
||||
$this->session
|
||||
->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue('AnotherUser'));
|
||||
|
||||
$this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
|
||||
}
|
||||
|
||||
public function testIsDavAuthenticatedWithCorrectDavSession() {
|
||||
$this->session
|
||||
->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
|
||||
$this->assertTrue($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
|
||||
}
|
||||
|
||||
public function testValidateUserPassOfAlreadyDAVAuthenticatedUser() {
|
||||
$user = $this->getMockBuilder('\OCP\IUser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$user->expects($this->exactly(2))
|
||||
->method('getUID')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('isLoggedIn')
|
||||
->will($this->returnValue(true));
|
||||
$this->userSession
|
||||
->expects($this->exactly(2))
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$this->session
|
||||
->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->method('close');
|
||||
|
||||
$this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
|
||||
}
|
||||
|
||||
public function testValidateUserPassOfInvalidDAVAuthenticatedUser() {
|
||||
$user = $this->getMockBuilder('\OCP\IUser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('isLoggedIn')
|
||||
->will($this->returnValue(true));
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$this->session
|
||||
->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue('AnotherUser'));
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->method('close');
|
||||
|
||||
$this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
|
||||
}
|
||||
|
||||
public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPassword() {
|
||||
$user = $this->getMockBuilder('\OCP\IUser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$user->expects($this->exactly(3))
|
||||
->method('getUID')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('isLoggedIn')
|
||||
->will($this->returnValue(true));
|
||||
$this->userSession
|
||||
->expects($this->exactly(3))
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$this->session
|
||||
->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue('AnotherUser'));
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('login')
|
||||
->with('MyTestUser', 'MyTestPassword')
|
||||
->will($this->returnValue(true));
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->method('set')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND', 'MyTestUser');
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->method('close');
|
||||
|
||||
$this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
|
||||
}
|
||||
|
||||
public function testValidateUserPassWithInvalidPassword() {
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('isLoggedIn')
|
||||
->will($this->returnValue(false));
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('login')
|
||||
->with('MyTestUser', 'MyTestPassword')
|
||||
->will($this->returnValue(false));
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->method('close');
|
||||
|
||||
$this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
|
||||
}
|
||||
|
||||
public function testGetCurrentUserWithoutBeingLoggedIn() {
|
||||
$this->assertSame(null, $this->auth->getCurrentUser());
|
||||
}
|
||||
|
||||
public function testGetCurrentUserWithValidDAVLogin() {
|
||||
$user = $this->getMockBuilder('\OCP\IUser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
$this->userSession
|
||||
->expects($this->exactly(2))
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$this->session
|
||||
->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
|
||||
$this->assertSame('MyTestUser', $this->auth->getCurrentUser());
|
||||
}
|
||||
|
||||
public function testGetCurrentUserWithoutAnyDAVLogin() {
|
||||
$user = $this->getMockBuilder('\OCP\IUser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
$this->userSession
|
||||
->expects($this->exactly(2))
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$this->session
|
||||
->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$this->assertSame('MyTestUser', $this->auth->getCurrentUser());
|
||||
}
|
||||
|
||||
public function testGetCurrentUserWithWrongDAVUser() {
|
||||
$user = $this->getMockBuilder('\OCP\IUser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('MyWrongDavUser'));
|
||||
$this->userSession
|
||||
->expects($this->exactly(2))
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$this->session
|
||||
->expects($this->exactly(3))
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue('AnotherUser'));
|
||||
|
||||
$this->assertSame(null, $this->auth->getCurrentUser());
|
||||
}
|
||||
|
||||
public function testAuthenticateAlreadyLoggedIn() {
|
||||
$server = $this->getMockBuilder('\Sabre\DAV\Server')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('isLoggedIn')
|
||||
->will($this->returnValue(true));
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('AUTHENTICATED_TO_DAV_BACKEND')
|
||||
->will($this->returnValue(null));
|
||||
$user = $this->getMockBuilder('\OCP\IUser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('MyWrongDavUser'));
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$this->session
|
||||
->expects($this->once())
|
||||
->method('close');
|
||||
|
||||
$this->assertTrue($this->auth->authenticate($server, 'TestRealm'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Sabre\DAV\Exception\NotAuthenticated
|
||||
* @expectedExceptionMessage No basic authentication headers were found
|
||||
*/
|
||||
public function testAuthenticateNoBasicAuthenticateHeadersProvided() {
|
||||
$server = $this->getMockBuilder('\Sabre\DAV\Server')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->auth->authenticate($server, 'TestRealm');
|
||||
}
|
||||
|
||||
public function testAuthenticateValidCredentials() {
|
||||
$server = $this->getMockBuilder('\Sabre\DAV\Server')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$server->httpRequest
|
||||
->expects($this->once())
|
||||
->method('getHeader')
|
||||
->with('Authorization')
|
||||
->will($this->returnValue('basic dXNlcm5hbWU6cGFzc3dvcmQ='));
|
||||
$server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('login')
|
||||
->with('username', 'password')
|
||||
->will($this->returnValue(true));
|
||||
$user = $this->getMockBuilder('\OCP\IUser')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$user->expects($this->exactly(2))
|
||||
->method('getUID')
|
||||
->will($this->returnValue('MyTestUser'));
|
||||
$this->userSession
|
||||
->expects($this->exactly(2))
|
||||
->method('getUser')
|
||||
->will($this->returnValue($user));
|
||||
$this->assertTrue($this->auth->authenticate($server, 'TestRealm'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Sabre\DAV\Exception\NotAuthenticated
|
||||
* @expectedExceptionMessage Username or password does not match
|
||||
*/
|
||||
public function testAuthenticateInvalidCredentials() {
|
||||
$server = $this->getMockBuilder('\Sabre\DAV\Server')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$server->httpRequest = $this->getMockBuilder('\Sabre\HTTP\RequestInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$server->httpRequest
|
||||
->expects($this->once())
|
||||
->method('getHeader')
|
||||
->with('Authorization')
|
||||
->will($this->returnValue('basic dXNlcm5hbWU6cGFzc3dvcmQ='));
|
||||
$server->httpResponse = $this->getMockBuilder('\Sabre\HTTP\ResponseInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('login')
|
||||
->with('username', 'password')
|
||||
->will($this->returnValue(false));
|
||||
$this->auth->authenticate($server, 'TestRealm');
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue