[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