PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

Implementing a WebDAV filesystem with PHP and SabreDAV

Authentication

The final step we must perform in creating a WebDAV server is to add authentication. SabreDAV makes it easy to add both basic and digest HTTP authentication.

Note however, that Windows users can only use basic authentication if the server is secure. In other words, non-SSL WebDAV servers must either use no authentication or they must use digest authentication.

As such, I will only show you how to add digest authentication. If you want to implement basic authentication, refer to http://code.google.com/p/sabredav/wiki/Authentication.

How Digest Works

When users authenticate with digest, they send only their username and a hash of their password. Their actual password is never actually sent across the wire.

All servers must define a realm, which is simply a name to identify the server. The realm name is also used when generating the password hash.

For the purposes of this article, we'll assume the name of the realm is web-dav-server. This name is not a secret, since it can easily be discovered by trying to connect to the protected resource.

When you store user information, you store their username and an MD5 of their username, the realm name and their password. So if their username is quentin, the realm name is web-dav-server, and their password is mypass, their hash would be calculated as follows:

Listing 8 Generating a digest authentication hash with PHP (listing-8.php)
<?php
    $username = 'quentin';
    $password = 'mypass';
    $realm    = 'web-dav-server';
 
    $hash = md5($username . ':' . $realm . ':' . $password);
?>

If you were storing user details in your web application's database, you would store the username and the created hash - you would not store their password.

Note: This also means you can't update their username without breaking their hash - you would need to reset their password.

Authenticating With SabreDAV

To authenticate with SabreDAV, we use the Sabre_HTTP_DigestAuth class. The authentication code appears before creating the WebDAV server and handling the request.

When a user tries to authenticate with HTTP digest, we have access to their submitted username. We must then look up the corresponding hash for the given username and tell Sabre_HTTP_DigestAuth what it is so it can check if the supplied hash matches our stored hash.

The following code demonstrates this. It contains two fictional functions (user_exists() and get_user_hash()) which you would replace with your real user checks.

Listing 9 Authenticating a request using SabreDAV's digest class (listing-9.php)
<?php
    require_once('Sabre.autoload.php');
 
    $realm = 'webdavserver';
 
    $auth = new Sabre_HTTP_DigestAuth();
    $auth->setRealm($realm);
    $auth->init();
 
    $username = $auth->getUsername();
 
    if (!user_exists($username)) {
        $auth->requireLogin();
        echo "Authentication required";
        exit;
    }
 
    $hash = get_user_hash($username);
 
    if (!$auth->validateA1($hash)) {
        $auth->requireLogin();
        echo "Authentication required";
        exit;
    }
 
    // valid user, handle their WebDAV request
?>

After setting setting the realm and retrieving the hash, we call the validateA1() method to check the supplied authentication details. If the hash is invalid we call requireLogin() to instruct Sabre_HTTP_DigestAuth request authentication.

Note: If you add this to a script and visit it in your browser, initially the browser tries to load the page and falls through to the requireLogin() method. Your browser then knows to ask you for a username and password then tries to load the page again.

In This Article