Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compatibility with ownCloud 9.1 #28

Merged
merged 2 commits into from
Mar 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ env:
- CORE_BRANCH=master DB=pgsql
- CORE_BRANCH=master DB=sqlite
- CORE_BRANCH=master DB=mysql
- CORE_BRANCH=stable9.1 DB=pgsql
- CORE_BRANCH=stable9.1 DB=sqlite
- CORE_BRANCH=stable9.1 DB=mysql

matrix:
allow_failures:
- php: 7.1
- php: nightly
- env: CORE_BRANCH=master
fast_finish: true

before_install:
Expand Down
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<namespace>OAuth2</namespace>
<category>other</category>
<dependencies>
<owncloud min-version="10" max-version="10"/>
<owncloud min-version="9.1" max-version="10"/>
</dependencies>
<types>
<authentication/>
Expand Down
142 changes: 142 additions & 0 deletions lib/Sabre/AbstractBearer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php

namespace OCA\OAuth2\Sabre;

use Sabre\DAV\Auth\Backend\BackendInterface;
use Sabre\HTTP;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;

/**
* Note: This file was imported from sabre/dav 3.2. It was necessary to import
* it in order to add compatibility with ownCloud 9.1, where an older version of
* this library is used.
*
* HTTP Bearer authentication backend class
*
* This class can be used by authentication objects wishing to use HTTP Bearer
* Most of the digest logic is handled, implementors just need to worry about
* the validateBearerToken method.
*
* @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
* @author François Kooman (https://tuxed.net/)
* @author James David Low (http://jameslow.com/)
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
abstract class AbstractBearer implements BackendInterface {

/**
* Authentication Realm.
*
* The realm is often displayed by browser clients when showing the
* authentication dialog.
*
* @var string
*/
protected $realm = 'sabre/dav';

/**
* Validates a Bearer token
*
* This method should return the full principal url, or false if the
* token was incorrect.
*
* @param string $bearerToken
* @return string|false
*/
abstract protected function validateBearerToken($bearerToken);

/**
* Sets the authentication realm for this backend.
*
* @param string $realm
* @return void
*/
function setRealm($realm) {

$this->realm = $realm;

}

/**
* When this method is called, the backend must check if authentication was
* successful.
*
* The returned value must be one of the following
*
* [true, "principals/username"]
* [false, "reason for failure"]
*
* 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]
*
* @param RequestInterface $request
* @param ResponseInterface $response
* @return array
*/
function check(RequestInterface $request, ResponseInterface $response) {

$auth = new HTTP\Auth\Bearer(
$this->realm,
$request,
$response
);

$bearerToken = $auth->getToken($request);
if (!$bearerToken) {
return [false, "No 'Authorization: Bearer' header found. Either the client didn't send one, or the server is mis-configured"];
}
$principalUrl = $this->validateBearerToken($bearerToken);
if (!$principalUrl) {
return [false, "Bearer token was incorrect"];
}
return [true, $principalUrl];

}

/**
* This method is called when a user could not be authenticated, and
* authentication was required for the current request.
*
* This gives you the opportunity to set authentication headers. The 401
* status code will already be set.
*
* In this case of Bearer Auth, this would for example mean that the
* following header needs to be set:
*
* $response->addHeader('WWW-Authenticate', 'Bearer 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.
*
* @param RequestInterface $request
* @param ResponseInterface $response
* @return void
*/
function challenge(RequestInterface $request, ResponseInterface $response) {

$auth = new HTTP\Auth\Bearer(
$this->realm,
$request,
$response
);
$auth->requireLogin();

}

}
1 change: 0 additions & 1 deletion lib/Sabre/OAuth2.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
use OCA\DAV\Connector\Sabre\Auth;
use OCP\IRequest;
use OCP\ISession;
use Sabre\DAV\Auth\Backend\AbstractBearer;

class OAuth2 extends AbstractBearer {

Expand Down
94 changes: 94 additions & 0 deletions tests/Unit/Sabre/AbstractBearerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace OCA\OAuth2\Tests\Unit\Sabre;

use OCA\OAuth2\Sabre\AbstractBearer;
use Sabre\HTTP;

/**
* Note: This file was imported from sabre/dav 3.2. It was necessary to import
* it in order to add compatibility with ownCloud 9.1, where an older version of
* this library is used.
*/
class AbstractBearerTest extends \PHPUnit_Framework_TestCase {

function testCheckNoHeaders() {

$request = new HTTP\Request();
$response = new HTTP\Response();

$backend = new AbstractBearerMock();

$this->assertFalse(
$backend->check($request, $response)[0]
);

}

function testCheckInvalidToken() {

$request = HTTP\Sapi::createFromServerArray([
'HTTP_AUTHORIZATION' => 'Bearer foo',
]);
$response = new HTTP\Response();

$backend = new AbstractBearerMock();

$this->assertFalse(
$backend->check($request, $response)[0]
);

}

function testCheckSuccess() {

$request = HTTP\Sapi::createFromServerArray([
'HTTP_AUTHORIZATION' => 'Bearer valid',
]);
$response = new HTTP\Response();

$backend = new AbstractBearerMock();
$this->assertEquals(
[true, 'principals/username'],
$backend->check($request, $response)
);

}

function testRequireAuth() {

$request = new HTTP\Request();
$response = new HTTP\Response();

$backend = new AbstractBearerMock();
$backend->setRealm('writing unittests on a saturday night');
$backend->challenge($request, $response);

$this->assertEquals(
'Bearer realm="writing unittests on a saturday night"',
$response->getHeader('WWW-Authenticate')
);

}

}


class AbstractBearerMock extends AbstractBearer {

/**
* Validates a bearer token
*
* This method should return true or false depending on if login
* succeeded.
*
* @param string $bearerToken
* @return bool
*/
function validateBearerToken($bearerToken) {

return 'valid' === $bearerToken ? 'principals/username' : false;

}

}