[Pkg-owncloud-commits] [php-sabredav] 56/64: Refactored authentication system to be stateless.
David Prévot
taffit at moszumanska.debian.org
Thu Dec 11 15:13:27 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to tag 2.2.0alpha1
in repository php-sabredav.
commit 559482163e934083b218b682978d7c76464db731
Author: Evert Pot <me at evertpot.com>
Date: Sat Dec 6 22:32:40 2014 -0500
Refactored authentication system to be stateless.
---
lib/DAV/Auth/Backend/AbstractBasic.php | 115 ++++++++++++++------
lib/DAV/Auth/Backend/AbstractDigest.php | 104 +++++++++++++-----
lib/DAV/Auth/Backend/Apache.php | 74 +++++++++----
lib/DAV/Auth/Backend/BackendInterface.php | 57 ++++++++--
lib/DAV/Auth/Plugin.php | 87 +++++++++------
tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php | 51 ++++-----
.../Sabre/DAV/Auth/Backend/AbstractDigestTest.php | 118 +++++++++------------
tests/Sabre/DAV/Auth/Backend/ApacheTest.php | 41 ++++---
tests/Sabre/DAV/Auth/Backend/BasicCallBackTest.php | 14 ++-
tests/Sabre/DAV/Auth/Backend/Mock.php | 80 +++++++++++---
tests/Sabre/DAV/Auth/PluginTest.php | 47 +++-----
11 files changed, 491 insertions(+), 297 deletions(-)
diff --git a/lib/DAV/Auth/Backend/AbstractBasic.php b/lib/DAV/Auth/Backend/AbstractBasic.php
index c46047f..5222a25 100644
--- a/lib/DAV/Auth/Backend/AbstractBasic.php
+++ b/lib/DAV/Auth/Backend/AbstractBasic.php
@@ -2,8 +2,11 @@
namespace Sabre\DAV\Auth\Backend;
-use Sabre\DAV;
-use Sabre\HTTP;
+use
+ Sabre\DAV,
+ Sabre\HTTP,
+ Sabre\HTTP\RequestInterface,
+ Sabre\HTTP\ResponseInterface;
/**
* HTTP Basic authentication backend class
@@ -20,11 +23,21 @@ use Sabre\HTTP;
abstract class AbstractBasic implements BackendInterface {
/**
- * This variable holds the currently logged in username.
+ * Authentication Realm.
*
- * @var string|null
+ * The realm is often displayed by browser clients when showing the
+ * authentication dialog.
+ *
+ * @var string
*/
- protected $currentUser;
+ protected $realm = 'sabre/dav';
+
+ /**
+ * This is the prefix that will be used to generate principal urls.
+ *
+ * @var string
+ */
+ protected $principalPrefix = 'principals/';
/**
* Validates a username and password
@@ -39,46 +52,82 @@ abstract class AbstractBasic implements BackendInterface {
abstract protected function validateUserPass($username, $password);
/**
- * Returns information about the currently logged in username.
+ * When this method is called, the backend must check if authentication was
+ * successful.
*
- * If nobody is currently logged in, this method should return null.
+ * This method should simply return null if authentication was not
+ * successful.
*
- * @return string|null
- */
- function getCurrentUser() {
- return $this->currentUser;
- }
-
-
- /**
- * Authenticates the user based on the current request.
+ * If authentication was successful, it's expected that the authentication
+ * backend returns a so-called principal url.
*
- * If authentication is successful, true must be returned.
- * If authentication fails, an exception must be thrown.
+ * Examples of a principal url:
*
- * @param DAV\Server $server
- * @param string $realm
- * @throws DAV\Exception\NotAuthenticated
- * @return bool
+ * principals/admin
+ * principals/user1
+ * principals/users/joe
+ * principals/uid/123457
+ *
+ * If you don't use WebDAV ACL (RFC3744) we recommend that you simply
+ * return a string such as:
+ *
+ * principals/users/[username]
+ *
+ * But literally any non-null value will be accepted as a 'succesful
+ * authentication'.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return null|string
*/
- function authenticate(DAV\Server $server, $realm) {
+ function check(RequestInterface $request, ResponseInterface $response) {
+
+ $auth = new HTTP\Auth\Basic(
+ $this->realm,
+ $request,
+ $response
+ );
- $auth = new HTTP\Auth\Basic($realm, $server->httpRequest, $server->httpResponse);
- $userpass = $auth->getCredentials($server->httpRequest);
+ $userpass = $auth->getCredentials($request);
if (!$userpass) {
- $auth->requireLogin();
- throw new DAV\Exception\NotAuthenticated('No basic authentication headers were found');
+ return null;
}
-
- // Authenticates the user
if (!$this->validateUserPass($userpass[0],$userpass[1])) {
- $auth->requireLogin();
- throw new DAV\Exception\NotAuthenticated('Username or password does not match');
+ return null;
}
- $this->currentUser = $userpass[0];
- return true;
+ return $this->principalPrefix . $userpass[0];
+
}
+ /**
+ * This method is called when a user could not be authenticated, and
+ * authentication was required for the current request.
+ *
+ * This gives you the oppurtunity to set authentication headers. The 401
+ * status code will already be set.
+ *
+ * In this case of Basic Auth, this would for example mean that the
+ * following header needs to be set:
+ *
+ * $response->addHeader('WWW-Authenticate', 'Basic realm=SabreDAV');
+ *
+ * Keep in mind that in the case of multiple authentication backends, other
+ * WWW-Authenticate headers may already have been set, and you'll want to
+ * append your own WWW-Authenticate header instead of overwriting the
+ * existing one.
+ *
+ * @return void
+ */
+ function requireAuth(RequestInterface $request, ResponseInterface $response) {
+
+ $auth = new HTTP\Auth\Basic(
+ $this->realm,
+ $request,
+ $response
+ );
+ $auth->requireLogin();
+
+ }
}
diff --git a/lib/DAV/Auth/Backend/AbstractDigest.php b/lib/DAV/Auth/Backend/AbstractDigest.php
index a1a74b0..bb423b7 100644
--- a/lib/DAV/Auth/Backend/AbstractDigest.php
+++ b/lib/DAV/Auth/Backend/AbstractDigest.php
@@ -4,7 +4,9 @@ namespace Sabre\DAV\Auth\Backend;
use
Sabre\HTTP,
- Sabre\DAV;
+ Sabre\DAV,
+ Sabre\HTTP\RequestInterface,
+ Sabre\HTTP\ResponseInterface;
/**
* HTTP Digest authentication backend class
@@ -20,11 +22,21 @@ use
abstract class AbstractDigest implements BackendInterface {
/**
- * This variable holds the currently logged in username.
+ * Authentication Realm.
*
- * @var array|null
+ * The realm is often displayed by browser clients when showing the
+ * authentication dialog.
+ *
+ * @var string
+ */
+ protected $realm = 'SabreDAV';
+
+ /**
+ * This is the prefix that will be used to generate principal urls.
+ *
+ * @var string
*/
- protected $currentUser;
+ protected $principalPrefix = 'principals/';
/**
* Returns a users digest hash based on the username and realm.
@@ -38,34 +50,54 @@ abstract class AbstractDigest implements BackendInterface {
abstract function getDigestHash($realm, $username);
/**
- * Authenticates the user based on the current request.
+ * When this method is called, the backend must check if authentication was
+ * successful.
*
- * If authentication is successful, true must be returned.
- * If authentication fails, an exception must be thrown.
+ * This method should simply return null if authentication was not
+ * successful.
*
- * @param DAV\Server $server
- * @param string $realm
- * @throws DAV\Exception\NotAuthenticated
- * @return bool
+ * If authentication was successful, it's expected that the authentication
+ * backend returns a so-called principal url.
+ *
+ * Examples of a principal url:
+ *
+ * principals/admin
+ * principals/user1
+ * principals/users/joe
+ * principals/uid/123457
+ *
+ * If you don't use WebDAV ACL (RFC3744) we recommend that you simply
+ * return a string such as:
+ *
+ * principals/users/[username]
+ *
+ * But literally any non-null value will be accepted as a 'succesful
+ * authentication'.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return null|string
*/
- function authenticate(DAV\Server $server, $realm) {
+ function check(RequestInterface $request, ResponseInterface $response) {
- $digest = new HTTP\Auth\Digest($realm, $server->httpRequest, $server->httpResponse);
+ $digest = new HTTP\Auth\Digest(
+ $this->realm,
+ $request,
+ $response
+ );
$digest->init();
$username = $digest->getUsername();
// No username was given
if (!$username) {
- $digest->requireLogin();
- throw new DAV\Exception\NotAuthenticated('No digest authentication headers were found');
+ return null;
}
- $hash = $this->getDigestHash($realm, $username);
+ $hash = $this->getDigestHash($this->realm, $username);
// If this was false, the user account didn't exist
if ($hash===false || is_null($hash)) {
- $digest->requireLogin();
- throw new DAV\Exception\NotAuthenticated('The supplied username was not on file');
+ return null;
}
if (!is_string($hash)) {
throw new DAV\Exception('The returned value from getDigestHash must be a string or null');
@@ -73,23 +105,41 @@ abstract class AbstractDigest implements BackendInterface {
// If this was false, the password or part of the hash was incorrect.
if (!$digest->validateA1($hash)) {
- $digest->requireLogin();
- throw new DAV\Exception\NotAuthenticated('Incorrect username');
+ return null;
}
- $this->currentUser = $username;
- return true;
+ return $this->principalPrefix . $username;
}
/**
- * Returns the currently logged in username.
+ * This method is called when a user could not be authenticated, and
+ * authentication was required for the current request.
*
- * @return string|null
+ * This gives you the oppurtunity to set authentication headers. The 401
+ * status code will already be set.
+ *
+ * In this case of Basic Auth, this would for example mean that the
+ * following header needs to be set:
+ *
+ * $response->addHeader('WWW-Authenticate', 'Basic realm=SabreDAV');
+ *
+ * Keep in mind that in the case of multiple authentication backends, other
+ * WWW-Authenticate headers may already have been set, and you'll want to
+ * append your own WWW-Authenticate header instead of overwriting the
+ * existing one.
+ *
+ * @return void
*/
- function getCurrentUser() {
-
- return $this->currentUser;
+ function requireAuth(RequestInterface $request, ResponseInterface $response) {
+
+ $auth = new HTTP\Auth\Digest(
+ $this->realm,
+ $request,
+ $response
+ );
+ $auth->init();
+ $auth->requireLogin();
}
diff --git a/lib/DAV/Auth/Backend/Apache.php b/lib/DAV/Auth/Backend/Apache.php
index bc6bb75..b7c01f4 100644
--- a/lib/DAV/Auth/Backend/Apache.php
+++ b/lib/DAV/Auth/Backend/Apache.php
@@ -1,7 +1,11 @@
<?php
namespace Sabre\DAV\Auth\Backend;
-use Sabre\DAV;
+
+use
+ Sabre\DAV,
+ Sabre\HTTP\RequestInterface,
+ Sabre\HTTP\ResponseInterface;
/**
* Apache authenticator
@@ -18,47 +22,75 @@ use Sabre\DAV;
class Apache implements BackendInterface {
/**
- * Current apache user
+ * This is the prefix that will be used to generate principal urls.
*
* @var string
*/
- protected $remoteUser;
+ protected $principalPrefix = 'principals/';
/**
- * Authenticates the user based on the current request.
+ * When this method is called, the backend must check if authentication was
+ * successful.
+ *
+ * This method should simply return null if authentication was not
+ * successful.
+ *
+ * If authentication was successful, it's expected that the authentication
+ * backend returns a so-called principal url.
+ *
+ * Examples of a principal url:
+ *
+ * principals/admin
+ * principals/user1
+ * principals/users/joe
+ * principals/uid/123457
+ *
+ * If you don't use WebDAV ACL (RFC3744) we recommend that you simply
+ * return a string such as:
*
- * If authentication is successful, true must be returned.
- * If authentication fails, an exception must be thrown.
+ * principals/users/[username]
*
- * @param DAV\Server $server
- * @param string $realm
- * @return bool
+ * But literally any non-null value will be accepted as a 'succesful
+ * authentication'.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return null|string
*/
- function authenticate(DAV\Server $server, $realm) {
+ function check(RequestInterface $request, ResponseInterface $response) {
- $remoteUser = $server->httpRequest->getRawServerValue('REMOTE_USER');
+ $remoteUser = $request->getRawServerValue('REMOTE_USER');
if (is_null($remoteUser)) {
- $remoteUser = $server->httpRequest->getRawServerValue('REDIRECT_REMOTE_USER');
+ $remoteUser = $request->getRawServerValue('REDIRECT_REMOTE_USER');
}
if (is_null($remoteUser)) {
- throw new DAV\Exception('We did not receive the $_SERVER[REMOTE_USER] property. This means that apache might have been misconfigured');
+ return null;
}
- $this->remoteUser = $remoteUser;
- return true;
+ return $this->principalPrefix . $remoteUser;
}
/**
- * Returns information about the currently logged in user.
+ * This method is called when a user could not be authenticated, and
+ * authentication was required for the current request.
+ *
+ * This gives you the oppurtunity to set authentication headers. The 401
+ * status code will already be set.
+ *
+ * In this case of Basic Auth, this would for example mean that the
+ * following header needs to be set:
*
- * If nobody is currently logged in, this method should return null.
+ * $response->addHeader('WWW-Authenticate', 'Basic realm=SabreDAV');
*
- * @return array|null
+ * Keep in mind that in the case of multiple authentication backends, other
+ * WWW-Authenticate headers may already have been set, and you'll want to
+ * append your own WWW-Authenticate header instead of overwriting the
+ * existing one.
+ *
+ * @return void
*/
- function getCurrentUser() {
-
- return $this->remoteUser;
+ function requireAuth(RequestInterface $request, ResponseInterface $response) {
}
diff --git a/lib/DAV/Auth/Backend/BackendInterface.php b/lib/DAV/Auth/Backend/BackendInterface.php
index b8d04e2..954a9ed 100644
--- a/lib/DAV/Auth/Backend/BackendInterface.php
+++ b/lib/DAV/Auth/Backend/BackendInterface.php
@@ -2,6 +2,10 @@
namespace Sabre\DAV\Auth\Backend;
+use
+ Sabre\HTTP\RequestInterface,
+ Sabre\HTTP\ResponseInterface;
+
/**
* This is the base class for any authentication object.
*
@@ -12,25 +16,56 @@ namespace Sabre\DAV\Auth\Backend;
interface BackendInterface {
/**
- * Authenticates the user based on the current request.
+ * When this method is called, the backend must check if authentication was
+ * successful.
+ *
+ * This method should simply return null if authentication was not
+ * successful.
+ *
+ * If authentication was successful, it's expected that the authentication
+ * backend returns a so-called principal url.
+ *
+ * Examples of a principal url:
+ *
+ * principals/admin
+ * principals/user1
+ * principals/users/joe
+ * principals/uid/123457
*
- * If authentication is successful, true must be returned.
- * If authentication fails, an exception must be thrown.
+ * If you don't use WebDAV ACL (RFC3744) we recommend that you simply
+ * return a string such as:
*
- * @param \Sabre\DAV\Server $server
- * @param string $realm
- * @return bool
+ * principals/users/[username]
+ *
+ * But literally any non-null value will be accepted as a 'succesful
+ * authentication'.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return null|string
*/
- function authenticate(\Sabre\DAV\Server $server,$realm);
+ function check(RequestInterface $request, ResponseInterface $response);
/**
- * Returns information about the currently logged in username.
+ * This method is called when a user could not be authenticated, and
+ * authentication was required for the current request.
+ *
+ * This gives you the oppurtunity to set authentication headers. The 401
+ * status code will already be set.
+ *
+ * In this case of Basic Auth, this would for example mean that the
+ * following header needs to be set:
+ *
+ * $response->addHeader('WWW-Authenticate', 'Basic realm=SabreDAV');
*
- * If nobody is currently logged in, this method should return null.
+ * Keep in mind that in the case of multiple authentication backends, other
+ * WWW-Authenticate headers may already have been set, and you'll want to
+ * append your own WWW-Authenticate header instead of overwriting the
+ * existing one.
*
- * @return string|null
+ * @return void
*/
- function getCurrentUser();
+ function requireAuth(RequestInterface $request, ResponseInterface $response);
}
diff --git a/lib/DAV/Auth/Plugin.php b/lib/DAV/Auth/Plugin.php
index a9a691f..5ce2633 100644
--- a/lib/DAV/Auth/Plugin.php
+++ b/lib/DAV/Auth/Plugin.php
@@ -3,29 +3,29 @@
namespace Sabre\DAV\Auth;
use
- Sabre\DAV,
Sabre\HTTP\RequestInterface,
- Sabre\HTTP\ResponseInterface;
+ Sabre\HTTP\ResponseInterface,
+ Sabre\HTTP\URLUtil,
+ Sabre\DAV\Exception\NotAuthenticated,
+ Sabre\DAV\Server,
+ Sabre\DAV\ServerPlugin;
+
/**
* This plugin provides Authentication for a WebDAV server.
*
* It relies on a Backend object, which provides user information.
*
- * Additionally, it provides support for:
- * * {DAV:}current-user-principal property from RFC5397
- * * {DAV:}principal-collection-set property from RFC3744
- *
* @copyright Copyright (C) 2007-2014 fruux GmbH (https://fruux.com/).
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
-class Plugin extends DAV\ServerPlugin {
+class Plugin extends ServerPlugin {
/**
* Reference to main server object
*
- * @var Sabre\DAV\Server
+ * @var Server
*/
protected $server;
@@ -37,39 +37,31 @@ class Plugin extends DAV\ServerPlugin {
protected $authBackend;
/**
- * The authentication realm.
+ * The currently logged in principal. Will be `null` if nobody is currently
+ * logged in.
*
- * @var string
+ * @var string|null
*/
- private $realm;
+ protected $currentPrincipal;
/**
- * @return string
- */
- function getRealm() {
- return $this->realm;
- }
-
- /**
- * __construct
+ * Creates the authentication plugin
*
* @param Backend\BackendInterface $authBackend
- * @param string $realm
*/
- function __construct(Backend\BackendInterface $authBackend, $realm) {
+ function __construct(Backend\BackendInterface $authBackend) {
$this->authBackend = $authBackend;
- $this->realm = $realm;
}
/**
* Initializes the plugin. This function is automatically called by the server
*
- * @param DAV\Server $server
+ * @param Server $server
* @return void
*/
- function initialize(DAV\Server $server) {
+ function initialize(Server $server) {
$this->server = $server;
$this->server->on('beforeMethod', [$this,'beforeMethod'], 10);
@@ -91,18 +83,41 @@ class Plugin extends DAV\ServerPlugin {
}
/**
- * Returns the current users' principal uri.
+ * Returns the currently logged-in principal.
+ *
+ * This will return a string such as:
+ *
+ * principals/username
+ * principals/users/username
+ *
+ * This method will return null if nobody is logged in.
+ *
+ * @return string|null
+ */
+ function getCurrentPrincipal() {
+
+ return $this->currentPrincipal;
+
+ }
+
+ /**
+ * Returns the current username.
*
- * If nobody is logged in, this will return null.
+ * This method is deprecated and is only kept for backwards compatibility
+ * purposes. Please switch to getCurrentPrincipal().
*
+ * @deprecated Will be removed in a future version!
* @return string|null
*/
function getCurrentUser() {
- $userInfo = $this->authBackend->getCurrentUser();
- if (!$userInfo) return null;
+ // We just do a 'basename' on the principal to give back a sane value
+ // here.
+ list(, $userName) = URLUtil::splitPath(
+ $this->getCurrentPrincipal()
+ );
- return $userInfo;
+ return $userName;
}
@@ -115,7 +130,19 @@ class Plugin extends DAV\ServerPlugin {
*/
function beforeMethod(RequestInterface $request, ResponseInterface $response) {
- $this->authBackend->authenticate($this->server,$this->getRealm());
+ $this->currentPrincipal = $this->authBackend->check(
+ $request,
+ $response
+ );
+
+ if (!$this->currentPrincipal) {
+ $this->authBackend->requireAuth($request, $response);
+ if (!$request->hasHeader('Authorization')) {
+ throw new NotAuthenticated('Authentication failed. We didn\'t see an Authorization header, this means that the client didn\'t try to authenticate, or that the server is mis-configured');
+ } else {
+ throw new NotAuthenticated('Authentication failed.');
+ }
+ }
}
diff --git a/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php b/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php
index 5952fe0..f156bfb 100644
--- a/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php
+++ b/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php
@@ -9,64 +9,51 @@ require_once 'Sabre/HTTP/ResponseMock.php';
class AbstractBasicTest extends \PHPUnit_Framework_TestCase {
- /**
- * @expectedException Sabre\DAV\Exception\NotAuthenticated
- */
- public function testAuthenticateNoHeaders() {
+ function testCheckNoHeaders() {
- $response = new HTTP\ResponseMock();
- $server = new DAV\Server();
- $server->httpResponse = $response;
+ $request = new HTTP\Request();
+ $response = new HTTP\Response();
$backend = new AbstractBasicMock();
- $backend->authenticate($server,'myRealm');
- }
+ $this->assertNull(
+ $backend->check($request, $response)
+ );
- /**
- * @expectedException Sabre\DAV\Exception\NotAuthenticated
- */
- public function testAuthenticateUnknownUser() {
+ }
- $response = new HTTP\ResponseMock();
- $tree = new DAV\Tree(new DAV\SimpleCollection('bla'));
- $server = new DAV\Server($tree);
- $server->httpResponse = $response;
+ function testCheckUnknownUser() {
$request = HTTP\Sapi::createFromServerArray(array(
'PHP_AUTH_USER' => 'username',
'PHP_AUTH_PW' => 'wrongpassword',
));
- $server->httpRequest = $request;
+ $response = new HTTP\Response();
$backend = new AbstractBasicMock();
- $backend->authenticate($server,'myRealm');
- }
+ $this->assertNull(
+ $backend->check($request, $response)
+ );
- public function testAuthenticate() {
+ }
- $response = new HTTP\ResponseMock();
- $tree = new DAV\Tree(new DAV\SimpleCollection('bla'));
- $server = new DAV\Server($tree);
- $server->httpResponse = $response;
+ function testAuthenticate() {
$request = HTTP\Sapi::createFromServerArray(array(
'PHP_AUTH_USER' => 'username',
'PHP_AUTH_PW' => 'password',
));
- $server->httpRequest = $request;
+ $response = new HTTP\Response();
$backend = new AbstractBasicMock();
- $this->assertTrue($backend->authenticate($server,'myRealm'));
-
- $result = $backend->getCurrentUser();
-
- $this->assertEquals('username', $result);
+ $this->assertEquals(
+ 'principals/username',
+ $backend->check($request, $response)
+ );
}
-
}
diff --git a/tests/Sabre/DAV/Auth/Backend/AbstractDigestTest.php b/tests/Sabre/DAV/Auth/Backend/AbstractDigestTest.php
index 9b6727c..dff5f9b 100644
--- a/tests/Sabre/DAV/Auth/Backend/AbstractDigestTest.php
+++ b/tests/Sabre/DAV/Auth/Backend/AbstractDigestTest.php
@@ -5,110 +5,94 @@ namespace Sabre\DAV\Auth\Backend;
use Sabre\DAV;
use Sabre\HTTP;
-require_once 'Sabre/HTTP/ResponseMock.php';
-
class AbstractDigestTest extends \PHPUnit_Framework_TestCase {
- /**
- * @expectedException Sabre\DAV\Exception\NotAuthenticated
- */
- public function testAuthenticateNoHeaders() {
+ function testCheckNoHeaders() {
- $response = new HTTP\ResponseMock();
- $server = new DAV\Server();
- $server->httpResponse = $response;
+ $request = new HTTP\Request();
+ $response = new HTTP\Response();
$backend = new AbstractDigestMock();
- $backend->authenticate($server,'myRealm');
+ $this->assertNull(
+ $backend->check($request, $response)
+ );
}
- /**
- * @expectedException Sabre\DAV\Exception
- */
- public function testAuthenticateBadGetUserInfoResponse() {
-
- $response = new HTTP\ResponseMock();
- $server = new DAV\Server();
- $server->httpResponse = $response;
+ function testCheckBadGetUserInfoResponse() {
$header = 'username=null, realm=myRealm, nonce=12345, uri=/, response=HASH, opaque=1, qop=auth, nc=1, cnonce=1';
- $request = HTTP\Sapi::createFromServerArray(array(
+ $request = HTTP\Sapi::createFromServerArray([
'PHP_AUTH_DIGEST' => $header,
- ));
- $server->httpRequest = $request;
+ ]);
+ $response = new HTTP\Response();
$backend = new AbstractDigestMock();
- $backend->authenticate($server,'myRealm');
+ $this->assertNull(
+ $backend->check($request, $response)
+ );
+
+ $backend = new AbstractDigestMock();
+ $backend->check($request, $response);
}
/**
* @expectedException Sabre\DAV\Exception
*/
- public function testAuthenticateBadGetUserInfoResponse2() {
-
- $response = new HTTP\ResponseMock();
- $server = new DAV\Server();
- $server->httpResponse = $response;
+ function testCheckBadGetUserInfoResponse2() {
$header = 'username=array, realm=myRealm, nonce=12345, uri=/, response=HASH, opaque=1, qop=auth, nc=1, cnonce=1';
- $request = HTTP\Sapi::createFromServerArray(array(
+ $request = HTTP\Sapi::createFromServerArray([
'PHP_AUTH_DIGEST' => $header,
- ));
- $server->httpRequest = $request;
+ ]);
+
+ $response = new HTTP\Response();
$backend = new AbstractDigestMock();
- $backend->authenticate($server,'myRealm');
+ $this->assertNull(
+ $backend->check($request, $response)
+ );
- }
+ $backend = new AbstractDigestMock();
+ $backend->check($request, $response);
- /**
- * @expectedException Sabre\DAV\Exception\NotAuthenticated
- */
- public function testAuthenticateUnknownUser() {
+ }
- $response = new HTTP\ResponseMock();
- $server = new DAV\Server();
- $server->httpResponse = $response;
+ function testCheckUnknownUser() {
$header = 'username=false, realm=myRealm, nonce=12345, uri=/, response=HASH, opaque=1, qop=auth, nc=1, cnonce=1';
- $request = HTTP\Sapi::createFromServerArray(array(
+ $request = HTTP\Sapi::createFromServerArray([
'PHP_AUTH_DIGEST' => $header,
- ));
- $server->httpRequest = $request;
+ ]);
+
+ $response = new HTTP\Response();
$backend = new AbstractDigestMock();
- $backend->authenticate($server,'myRealm');
+ $this->assertNull(
+ $backend->check($request, $response)
+ );
}
- /**
- * @expectedException Sabre\DAV\Exception\NotAuthenticated
- */
- public function testAuthenticateBadPassword() {
-
- $response = new HTTP\ResponseMock();
- $server = new DAV\Server();
- $server->httpResponse = $response;
+ function testCheckBadPassword() {
$header = 'username=user, realm=myRealm, nonce=12345, uri=/, response=HASH, opaque=1, qop=auth, nc=1, cnonce=1';
- $request = HTTP\Sapi::createFromServerArray(array(
+ $request = HTTP\Sapi::createFromServerArray([
'PHP_AUTH_DIGEST' => $header,
'REQUEST_METHOD' => 'PUT',
- ));
- $server->httpRequest = $request;
+ ]);
+
+ $response = new HTTP\Response();
$backend = new AbstractDigestMock();
- $backend->authenticate($server,'myRealm');
+ $this->assertNull(
+ $backend->check($request, $response)
+ );
}
- public function testAuthenticate() {
-
- $response = new HTTP\ResponseMock();
- $server = new DAV\Server();
- $server->httpResponse = $response;
+ function testCheck() {
$digestHash = md5('HELLO:12345:1:1:auth:' . md5('GET:/'));
$header = 'username=user, realm=myRealm, nonce=12345, uri=/, response='.$digestHash.', opaque=1, qop=auth, nc=1, cnonce=1';
@@ -117,19 +101,17 @@ class AbstractDigestTest extends \PHPUnit_Framework_TestCase {
'PHP_AUTH_DIGEST' => $header,
'REQUEST_URI' => '/',
));
- $server->httpRequest = $request;
- $backend = new AbstractDigestMock();
- $this->assertTrue($backend->authenticate($server,'myRealm'));
-
- $result = $backend->getCurrentUser();
+ $response = new HTTP\Response();
- $this->assertEquals('user', $result);
- $this->assertEquals('HELLO', $backend->getDigestHash('myRealm', $result));
+ $backend = new AbstractDigestMock();
+ $this->assertEquals(
+ 'principals/user',
+ $backend->check($request, $response)
+ );
}
-
}
diff --git a/tests/Sabre/DAV/Auth/Backend/ApacheTest.php b/tests/Sabre/DAV/Auth/Backend/ApacheTest.php
index 4d04a2a..6532169 100644
--- a/tests/Sabre/DAV/Auth/Backend/ApacheTest.php
+++ b/tests/Sabre/DAV/Auth/Backend/ApacheTest.php
@@ -14,50 +14,45 @@ class ApacheTest extends \PHPUnit_Framework_TestCase {
}
- /**
- * @expectedException Sabre\DAV\Exception
- */
function testNoHeader() {
- $server = new DAV\Server();
+ $request = new HTTP\Request();
+ $response = new HTTP\Response();
$backend = new Apache();
- $backend->authenticate($server,'Realm');
+
+ $this->assertNull(
+ $backend->check($request, $response)
+ );
}
function testRemoteUser() {
- $backend = new Apache();
-
- $server = new DAV\Server();
$request = HTTP\Sapi::createFromServerArray([
'REMOTE_USER' => 'username',
]);
- $server->httpRequest = $request;
-
- $this->assertTrue($backend->authenticate($server, 'Realm'));
-
- $userInfo = 'username';
+ $response = new HTTP\Response();
+ $backend = new Apache();
- $this->assertEquals($userInfo, $backend->getCurrentUser());
+ $this->assertEquals(
+ 'principals/username',
+ $backend->check($request, $response)
+ );
}
function testRedirectRemoteUser() {
- $backend = new Apache();
-
- $server = new DAV\Server();
$request = HTTP\Sapi::createFromServerArray([
'REDIRECT_REMOTE_USER' => 'username',
]);
- $server->httpRequest = $request;
-
- $this->assertTrue($backend->authenticate($server, 'Realm'));
-
- $userInfo = 'username';
+ $response = new HTTP\Response();
+ $backend = new Apache();
- $this->assertEquals($userInfo, $backend->getCurrentUser());
+ $this->assertEquals(
+ 'principals/username',
+ $backend->check($request, $response)
+ );
}
}
diff --git a/tests/Sabre/DAV/Auth/Backend/BasicCallBackTest.php b/tests/Sabre/DAV/Auth/Backend/BasicCallBackTest.php
index a1750d0..74d59e8 100644
--- a/tests/Sabre/DAV/Auth/Backend/BasicCallBackTest.php
+++ b/tests/Sabre/DAV/Auth/Backend/BasicCallBackTest.php
@@ -4,13 +4,14 @@ namespace Sabre\DAV\Auth\Backend;
use
Sabre\DAV\Server,
- Sabre\HTTP\Sapi;
+ Sabre\HTTP\Sapi,
+ Sabre\HTTP\Response;
class BasicCallBackTest extends \PHPUnit_Framework_TestCase {
function testCallBack() {
- $args = array();
+ $args = [];
$callBack = function($user, $pass) use (&$args) {
$args = [$user, $pass];
@@ -20,12 +21,15 @@ class BasicCallBackTest extends \PHPUnit_Framework_TestCase {
$backend = new BasicCallBack($callBack);
- $server = new Server();
- $server->httpRequest = Sapi::createFromServerArray([
+ $request = Sapi::createFromServerArray([
'HTTP_AUTHORIZATION' => 'Basic ' . base64_encode('foo:bar'),
]);
+ $response = new Response();
- $this->assertTrue($backend->authenticate($server, 'Realm'));
+ $this->assertEquals(
+ 'principals/foo',
+ $backend->check($request, $response)
+ );
$this->assertEquals(['foo','bar'], $args);
diff --git a/tests/Sabre/DAV/Auth/Backend/Mock.php b/tests/Sabre/DAV/Auth/Backend/Mock.php
index fdad8a6..ffb0d4b 100644
--- a/tests/Sabre/DAV/Auth/Backend/Mock.php
+++ b/tests/Sabre/DAV/Auth/Backend/Mock.php
@@ -2,35 +2,83 @@
namespace Sabre\DAV\Auth\Backend;
-use Sabre\DAV;
+use
+ Sabre\DAV,
+ Sabre\HTTP\RequestInterface,
+ Sabre\HTTP\ResponseInterface;
class Mock implements BackendInterface {
- protected $currentUser;
+ public $fail = false;
- public $defaultUser = 'admin';
+ public $principal;
+ public $defaultPrincipal = 'principals/admin';
- /**
- * @param Sabre\DAV\Server $server
- * @param string $realm
- * @throws Sabre\DAV\Exception\NotAuthenticated
- */
- function authenticate(DAV\Server $server, $realm) {
+ function setPrincipal($principal) {
- if ($realm=='failme') throw new DAV\Exception\NotAuthenticated('deliberate fail');
- $this->currentUser = $this->defaultUser;
+ $this->principal = $principal;
}
- function setCurrentUser($user) {
+ /**
+ * When this method is called, the backend must check if authentication was
+ * successful.
+ *
+ * This method should simply return null if authentication was not
+ * successful.
+ *
+ * If authentication was successful, it's expected that the authentication
+ * backend returns a so-called principal url.
+ *
+ * Examples of a principal url:
+ *
+ * principals/admin
+ * principals/user1
+ * principals/users/joe
+ * principals/uid/123457
+ *
+ * If you don't use WebDAV ACL (RFC3744) we recommend that you simply
+ * return a string such as:
+ *
+ * principals/users/[username]
+ *
+ * But literally any non-null value will be accepted as a 'succesful
+ * authentication'.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return null|string
+ */
+ function check(RequestInterface $request, ResponseInterface $response) {
- $this->currentUser = $user;
+ if ($this->fail) {
+ return null;
+ }
+ $this->principal = $this->defaultPrincipal;
+ return $this->principal;
}
- function getCurrentUser() {
-
- return $this->currentUser;
+ /**
+ * This method is called when a user could not be authenticated, and
+ * authentication was required for the current request.
+ *
+ * This gives you the oppurtunity to set authentication headers. The 401
+ * status code will already be set.
+ *
+ * In this case of Basic Auth, this would for example mean that the
+ * following header needs to be set:
+ *
+ * $response->addHeader('WWW-Authenticate', 'Basic realm=SabreDAV');
+ *
+ * Keep in mind that in the case of multiple authentication backends, other
+ * WWW-Authenticate headers may already have been set, and you'll want to
+ * append your own WWW-Authenticate header instead of overwriting the
+ * existing one.
+ *
+ * @return void
+ */
+ function requireAuth(RequestInterface $request, ResponseInterface $response) {
}
diff --git a/tests/Sabre/DAV/Auth/PluginTest.php b/tests/Sabre/DAV/Auth/PluginTest.php
index e267abd..3bc59d8 100644
--- a/tests/Sabre/DAV/Auth/PluginTest.php
+++ b/tests/Sabre/DAV/Auth/PluginTest.php
@@ -25,7 +25,7 @@ class PluginTest extends \PHPUnit_Framework_TestCase {
function testAuthenticate() {
$fakeServer = new DAV\Server( new DAV\SimpleCollection('bla'));
- $plugin = new Plugin(new Backend\Mock(),'realm');
+ $plugin = new Plugin(new Backend\Mock());
$fakeServer->addPlugin($plugin);
$this->assertTrue(
$fakeServer->emit('beforeMethod', [new HTTP\Request(), new HTTP\Response()])
@@ -40,55 +40,40 @@ class PluginTest extends \PHPUnit_Framework_TestCase {
function testAuthenticateFail() {
$fakeServer = new DAV\Server( new DAV\SimpleCollection('bla'));
- $plugin = new Plugin(new Backend\Mock(),'failme');
+ $backend = new Backend\Mock();
+ $backend->fail = true;
+
+ $plugin = new Plugin($backend);
$fakeServer->addPlugin($plugin);
$fakeServer->emit('beforeMethod', [new HTTP\Request(), new HTTP\Response()]);
}
- function testReportPassThrough() {
+ /**
+ * @depends testAuthenticate
+ */
+ function testGetCurrentPrincipal() {
- $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla'));
- $plugin = new Plugin(new Backend\Mock(),'realm');
+ $fakeServer = new DAV\Server( new DAV\SimpleCollection('bla'));
+ $plugin = new Plugin(new Backend\Mock());
$fakeServer->addPlugin($plugin);
-
- $request = HTTP\Sapi::createFromServerArray(array(
- 'REQUEST_METHOD' => 'REPORT',
- 'HTTP_CONTENT_TYPE' => 'application/xml',
- 'REQUEST_URI' => '/',
- ));
- $request->setBody('<?xml version="1.0"?><s:somereport xmlns:s="http://www.rooftopsolutions.nl/NS/example" />');
-
- $fakeServer->httpRequest = $request;
- $fakeServer->sapi = new HTTP\SapiMock();
- $fakeServer->httpResponse = new HTTP\ResponseMock();
- $fakeServer->exec();
-
- $this->assertEquals(415, $fakeServer->httpResponse->status);
+ $fakeServer->emit('beforeMethod', [new HTTP\Request(), new HTTP\Response()]);
+ $this->assertEquals('principals/admin', $plugin->getCurrentPrincipal());
}
/**
- * @depends testInit
+ * @depends testAuthenticate
*/
- function testGetCurrentUserPrincipal() {
+ function testGetCurrentUser() {
$fakeServer = new DAV\Server( new DAV\SimpleCollection('bla'));
- $plugin = new Plugin(new Backend\Mock(),'realm');
+ $plugin = new Plugin(new Backend\Mock());
$fakeServer->addPlugin($plugin);
$fakeServer->emit('beforeMethod', [new HTTP\Request(), new HTTP\Response()]);
$this->assertEquals('admin', $plugin->getCurrentUser());
}
- /**
- * @depends testInit
- */
- function testPlugin() {
- $myRealmName = 'some_realm';
- $plugin = new Plugin(new Backend\Mock(),$myRealmName);
- $this->assertEquals($myRealmName, $plugin->getRealm());
- }
-
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/php-sabredav.git
More information about the Pkg-owncloud-commits
mailing list