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