From 9711c3a61727374dfe888feddb1ff382cecc0f0e Mon Sep 17 00:00:00 2001 From: Jonathan Neugebauer Date: Mon, 20 Mar 2017 21:09:20 +0100 Subject: [PATCH 1/2] Add AbstractBearer class from sabre/dav for compatibility with ownCloud 9.1 --- .travis.yml | 4 +- appinfo/info.xml | 2 +- lib/Sabre/AbstractBearer.php | 142 +++++++++++++++++++++++++++++++++++ lib/Sabre/OAuth2.php | 1 - 4 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 lib/Sabre/AbstractBearer.php diff --git a/.travis.yml b/.travis.yml index 5a05fbb7..889355e7 100755 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/appinfo/info.xml b/appinfo/info.xml index 9754b233..74424cd6 100755 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -9,7 +9,7 @@ OAuth2 other - + diff --git a/lib/Sabre/AbstractBearer.php b/lib/Sabre/AbstractBearer.php new file mode 100644 index 00000000..2cd21630 --- /dev/null +++ b/lib/Sabre/AbstractBearer.php @@ -0,0 +1,142 @@ +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(); + + } + +} diff --git a/lib/Sabre/OAuth2.php b/lib/Sabre/OAuth2.php index d9c0eb15..fc6f79fd 100644 --- a/lib/Sabre/OAuth2.php +++ b/lib/Sabre/OAuth2.php @@ -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 { From 170acd97875fc9bbe1472131f943e57baa359e0a Mon Sep 17 00:00:00 2001 From: Jonathan Neugebauer Date: Wed, 22 Mar 2017 08:55:39 +0100 Subject: [PATCH 2/2] Add AbstractBearerTest --- tests/Unit/Sabre/AbstractBearerTest.php | 94 +++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/Unit/Sabre/AbstractBearerTest.php diff --git a/tests/Unit/Sabre/AbstractBearerTest.php b/tests/Unit/Sabre/AbstractBearerTest.php new file mode 100644 index 00000000..cf1b3ed5 --- /dev/null +++ b/tests/Unit/Sabre/AbstractBearerTest.php @@ -0,0 +1,94 @@ +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; + + } + +}