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