1<?php
2
3namespace Sabre\DAV\Auth\Backend;
4
5use Sabre\DAV;
6use Sabre\HTTP;
7use Sabre\HTTP\RequestInterface;
8use Sabre\HTTP\ResponseInterface;
9
10/**
11 * HTTP Basic authentication backend class
12 *
13 * This class can be used by authentication objects wishing to use HTTP Basic
14 * Most of the digest logic is handled, implementors just need to worry about
15 * the validateUserPass method.
16 *
17 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
18 * @author James David Low (http://jameslow.com/)
19 * @author Evert Pot (http://evertpot.com/)
20 * @license http://sabre.io/license/ Modified BSD License
21 */
22abstract class AbstractBasic implements BackendInterface {
23
24    /**
25     * Authentication Realm.
26     *
27     * The realm is often displayed by browser clients when showing the
28     * authentication dialog.
29     *
30     * @var string
31     */
32    protected $realm = 'sabre/dav';
33
34    /**
35     * This is the prefix that will be used to generate principal urls.
36     *
37     * @var string
38     */
39    protected $principalPrefix = 'principals/';
40
41    /**
42     * Validates a username and password
43     *
44     * This method should return true or false depending on if login
45     * succeeded.
46     *
47     * @param string $username
48     * @param string $password
49     * @return bool
50     */
51    abstract protected function validateUserPass($username, $password);
52
53    /**
54     * Sets the authentication realm for this backend.
55     *
56     * @param string $realm
57     * @return void
58     */
59    function setRealm($realm) {
60
61        $this->realm = $realm;
62
63    }
64
65    /**
66     * When this method is called, the backend must check if authentication was
67     * successful.
68     *
69     * The returned value must be one of the following
70     *
71     * [true, "principals/username"]
72     * [false, "reason for failure"]
73     *
74     * If authentication was successful, it's expected that the authentication
75     * backend returns a so-called principal url.
76     *
77     * Examples of a principal url:
78     *
79     * principals/admin
80     * principals/user1
81     * principals/users/joe
82     * principals/uid/123457
83     *
84     * If you don't use WebDAV ACL (RFC3744) we recommend that you simply
85     * return a string such as:
86     *
87     * principals/users/[username]
88     *
89     * @param RequestInterface $request
90     * @param ResponseInterface $response
91     * @return array
92     */
93    function check(RequestInterface $request, ResponseInterface $response) {
94
95        $auth = new HTTP\Auth\Basic(
96            $this->realm,
97            $request,
98            $response
99        );
100
101        $userpass = $auth->getCredentials();
102        if (!$userpass) {
103            return [false, "No 'Authorization: Basic' header found. Either the client didn't send one, or the server is misconfigured"];
104        }
105        if (!$this->validateUserPass($userpass[0], $userpass[1])) {
106            return [false, "Username or password was incorrect"];
107        }
108        return [true, $this->principalPrefix . $userpass[0]];
109
110    }
111
112    /**
113     * This method is called when a user could not be authenticated, and
114     * authentication was required for the current request.
115     *
116     * This gives you the opportunity to set authentication headers. The 401
117     * status code will already be set.
118     *
119     * In this case of Basic Auth, this would for example mean that the
120     * following header needs to be set:
121     *
122     * $response->addHeader('WWW-Authenticate', 'Basic realm=SabreDAV');
123     *
124     * Keep in mind that in the case of multiple authentication backends, other
125     * WWW-Authenticate headers may already have been set, and you'll want to
126     * append your own WWW-Authenticate header instead of overwriting the
127     * existing one.
128     *
129     * @param RequestInterface $request
130     * @param ResponseInterface $response
131     * @return void
132     */
133    function challenge(RequestInterface $request, ResponseInterface $response) {
134
135        $auth = new HTTP\Auth\Basic(
136            $this->realm,
137            $request,
138            $response
139        );
140        $auth->requireLogin();
141
142    }
143
144}
145