From 7924d6584d9eca0d4ef3bbdceaa020186205e109 Mon Sep 17 00:00:00 2001 From: Dipak Acharya Date: Thu, 19 Dec 2019 14:09:10 +0545 Subject: [PATCH] Add Tests for checking auth through app passwords and token --- .../features/apiAuth/tokenAuth.feature | 16 ++++ .../apiAuthWebDav/webDavDELETEAuth.feature | 24 +++++ .../apiAuthWebDav/webDavLOCKAuth.feature | 24 +++++ .../apiAuthWebDav/webDavMKCOLAuth.feature | 24 +++++ .../apiAuthWebDav/webDavMOVEAuth.feature | 25 ++++++ .../apiAuthWebDav/webDavPOSTAuth.feature | 25 ++++++ .../apiAuthWebDav/webDavPROPFINDAuth.feature | 24 +++++ .../apiAuthWebDav/webDavPROPPATCHAuth.feature | 24 +++++ .../apiAuthWebDav/webDavPUTAuth.feature | 26 ++++++ tests/acceptance/features/bootstrap/Auth.php | 90 ++++++++++++++++++- 10 files changed, 298 insertions(+), 4 deletions(-) diff --git a/tests/acceptance/features/apiAuth/tokenAuth.feature b/tests/acceptance/features/apiAuth/tokenAuth.feature index 162e51991cf8..14be7abbfb2d 100644 --- a/tests/acceptance/features/apiAuth/tokenAuth.feature +++ b/tests/acceptance/features/apiAuth/tokenAuth.feature @@ -24,6 +24,22 @@ Feature: tokenAuth When the user requests "/index.php/apps/files" with "GET" using the generated app password Then the HTTP status code should be "200" + Scenario: cannot access files app with an app password that is deleted when token auth is enforced + Given a new browser session for "user1" has been started + And the user has generated a new app password named "my-client" + And the user has deleted the app password named "my-client" + When the user requests "/index.php/apps/files" with "GET" using the generated app password + Then the HTTP status code should be "401" + + Scenario: Access files app with when there are multiple tokens generated + Given a new browser session for "user1" has been started + And the user has generated a new app password named "my-client" + And the user has generated a new app password named "my-new-client" + When the user requests "/index.php/apps/files" with "GET" using app password named "my-client" + Then the HTTP status code should be "200" + When the user requests "/index.php/apps/files" with "GET" using app password named "my-new-client" + Then the HTTP status code should be "200" + @smokeTest Scenario: cannot access files app with basic auth when token auth is enforced When user "user1" requests "/index.php/apps/files" with "GET" using basic auth diff --git a/tests/acceptance/features/apiAuthWebDav/webDavDELETEAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavDELETEAuth.feature index 9b0068425eaa..ee3e9ad2f244 100644 --- a/tests/acceptance/features/apiAuthWebDav/webDavDELETEAuth.feature +++ b/tests/acceptance/features/apiAuthWebDav/webDavDELETEAuth.feature @@ -56,3 +56,27 @@ Feature: delete file/folder | /remote.php/webdav/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send DELETE requests to webDav endpoints using token authentication should not work + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user requests these endpoints with "DELETE" using the generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send DELETE requests to webDav endpoints using app password token as password + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user "user0" requests these endpoints with "DELETE" using the basic auth and generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 204 | doesnotmatter | + | /remote.php/dav/files/user0/textfile1.txt | 204 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 204 | doesnotmatter | + | /remote.php/webdav/PARENT | 204 | doesnotmatter | + | /remote.php/dav/files/user0/FOLDER | 204 | doesnotmatter | diff --git a/tests/acceptance/features/apiAuthWebDav/webDavLOCKAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavLOCKAuth.feature index 5f3e4f5eb445..07c9100c91fc 100644 --- a/tests/acceptance/features/apiAuthWebDav/webDavLOCKAuth.feature +++ b/tests/acceptance/features/apiAuthWebDav/webDavLOCKAuth.feature @@ -56,3 +56,27 @@ Feature: LOCK file/folder | /remote.php/webdav/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send LOCK requests to webDav endpoints using token authentication should not work + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user requests these endpoints with "LOCK" using the generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send LOCK requests to webDav endpoints using app password token as password + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user "user0" requests these endpoints with "LOCK" using the basic auth and generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 200 | | + | /remote.php/dav/files/user0/textfile1.txt | 200 | | + | /remote.php/dav/files/user0/PARENT/parent.txt | 200 | | + | /remote.php/webdav/PARENT | 200 | | + | /remote.php/dav/files/user0/FOLDER | 200 | | diff --git a/tests/acceptance/features/apiAuthWebDav/webDavMKCOLAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavMKCOLAuth.feature index 9bc81eef5139..6940e09b12be 100644 --- a/tests/acceptance/features/apiAuthWebDav/webDavMKCOLAuth.feature +++ b/tests/acceptance/features/apiAuthWebDav/webDavMKCOLAuth.feature @@ -56,3 +56,27 @@ Feature: get file info using MKCOL | /remote.php/webdav/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send MKCOL requests to webDav endpoints using token authentication should not work + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user requests these endpoints with "MKCOL" using the generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send MKCOL requests to webDav endpoints using app password token as password + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user "user0" requests these endpoints with "MKCOL" using the basic auth and generated app password then the status codes should be as listed + | endpoint | http-code | + | /remote.php/webdav/newCol | 201 | + | /remote.php/dav/files/user0/newCol1 | 201 | + | /remote.php/dav/files/user0/PARENT/newCol | 201 | + | /remote.php/webdav/COL | 201 | + | /remote.php/dav/files/user0/FOLDER/newCol | 201 | diff --git a/tests/acceptance/features/apiAuthWebDav/webDavMOVEAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavMOVEAuth.feature index edc2d646e30f..2c959850a119 100644 --- a/tests/acceptance/features/apiAuthWebDav/webDavMOVEAuth.feature +++ b/tests/acceptance/features/apiAuthWebDav/webDavMOVEAuth.feature @@ -56,3 +56,28 @@ Feature: MOVE file/folder | /remote.php/webdav/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send MOVE requests to webDav endpoints using token authentication should not work + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user requests these endpoints with "MOVE" using the generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send MOVE requests to webDav endpoints using app password token as password + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user "user0" requests these endpoints with "MOVE" using the basic auth and generated app password then the status codes should be as listed + | endpoint | http-code | body | + # The token was valid and accepted but the body is invalid so it gives 403 + | /remote.php/webdav/textfile0.txt | 403 | doesnotmatter | + | /remote.php/dav/files/user0/textfile1.txt | 403 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 403 | doesnotmatter | + | /remote.php/webdav/PARENT | 403 | doesnotmatter | + | /remote.php/dav/files/user0/FOLDER | 403 | doesnotmatter | diff --git a/tests/acceptance/features/apiAuthWebDav/webDavPOSTAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavPOSTAuth.feature index a182078e91b2..e8838a90fab2 100644 --- a/tests/acceptance/features/apiAuthWebDav/webDavPOSTAuth.feature +++ b/tests/acceptance/features/apiAuthWebDav/webDavPOSTAuth.feature @@ -56,3 +56,28 @@ Feature: get file info using POST | /remote.php/webdav/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send POST requests to webDav endpoints using token authentication should not work + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user requests these endpoints with "POST" using the generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send POST requests to webDav endpoints using app password token as password + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user "user0" requests these endpoints with "POST" using the basic auth and generated app password then the status codes should be as listed + | endpoint | http-code | body | + # this method is not available so gives 501 + | /remote.php/webdav/textfile0.txt | 501 | doesnotmatter | + | /remote.php/dav/files/user0/textfile1.txt | 501 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 501 | doesnotmatter | + | /remote.php/webdav/PARENT | 501 | doesnotmatter | + | /remote.php/dav/files/user0/FOLDER | 501 | doesnotmatter | diff --git a/tests/acceptance/features/apiAuthWebDav/webDavPROPFINDAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavPROPFINDAuth.feature index 9291d6002c39..7456bbf4326d 100644 --- a/tests/acceptance/features/apiAuthWebDav/webDavPROPFINDAuth.feature +++ b/tests/acceptance/features/apiAuthWebDav/webDavPROPFINDAuth.feature @@ -56,3 +56,27 @@ Feature: get file info using PROPFIND | /remote.php/webdav/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send PROPFIND requests to webDav endpoints using token authentication should not work + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user requests these endpoints with "PROPFIND" using the generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send PROPFIND requests to webDav endpoints using app password token as password + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user "user0" requests these endpoints with "PROPFIND" using the basic auth and generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/dav/files/user0/textfile0.txt | 207 | | + | /remote.php/dav/files/user0/PARENT | 207 | | + | /remote.php/dav/files/user0/PARENT/parent.txt | 207 | | + | /remote.php/webdav/PARENT | 207 | | + | /remote.php/webdav/textfile0.txt | 207 | | diff --git a/tests/acceptance/features/apiAuthWebDav/webDavPROPPATCHAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavPROPPATCHAuth.feature index 49f945aaf90f..7cb269cd9c6d 100644 --- a/tests/acceptance/features/apiAuthWebDav/webDavPROPPATCHAuth.feature +++ b/tests/acceptance/features/apiAuthWebDav/webDavPROPPATCHAuth.feature @@ -56,3 +56,27 @@ Feature: PROPPATCH file/folder | /remote.php/webdav/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send PROPPATCH requests to webDav endpoints using token authentication should not work + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user requests these endpoints with "PROPPATCH" using the generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send PROPPATCH requests to webDav endpoints using app password token as password + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user "user0" requests these endpoints with "PROPPATCH" using the basic auth and generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 207 | 1 | + | /remote.php/dav/files/user0/textfile1.txt | 207 | 1 | + | /remote.php/dav/files/user0/PARENT/parent.txt | 207 | 1 | + | /remote.php/webdav/PARENT | 207 | 1 | + | /remote.php/dav/files/user0/FOLDER | 207 | 1 | diff --git a/tests/acceptance/features/apiAuthWebDav/webDavPUTAuth.feature b/tests/acceptance/features/apiAuthWebDav/webDavPUTAuth.feature index 3f2b24b7c4f7..b205ef518bb1 100644 --- a/tests/acceptance/features/apiAuthWebDav/webDavPUTAuth.feature +++ b/tests/acceptance/features/apiAuthWebDav/webDavPUTAuth.feature @@ -56,3 +56,29 @@ Feature: get file info using PUT | /remote.php/webdav/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send PUT requests to webDav endpoints using token authentication should not work + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user requests these endpoints with "PUT" using the generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 401 | doesnotmatter | + | /remote.php/dav/files/user0/textfile0.txt | 401 | doesnotmatter | + | /remote.php/webdav/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT | 401 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 401 | doesnotmatter | + + Scenario: send PUT requests to webDav endpoints using app password token as password + Given token auth has been enforced + And a new browser session for "user0" has been started + And the user has generated a new app password named "my-client" + When the user "user0" requests these endpoints with "PUT" using the basic auth and generated app password then the status codes should be as listed + | endpoint | http-code | body | + | /remote.php/webdav/textfile0.txt | 204 | doesnotmatter | + | /remote.php/dav/files/user0/textfile1.txt | 204 | doesnotmatter | + | /remote.php/dav/files/user0/PARENT/parent.txt | 204 | doesnotmatter | + | /remote.php/webdav/PARENS | 201 | doesnotmatter | + | /remote.php/dav/files/user0/FOLDERS | 201 | doesnotmatter | + # this folder already exists so gives 409 - CONFLICT + | /remote.php/dav/files/user0/FOLDER | 409 | doesnotmatter | diff --git a/tests/acceptance/features/bootstrap/Auth.php b/tests/acceptance/features/bootstrap/Auth.php index 377a98cc40b5..4b2fd50f8b6a 100644 --- a/tests/acceptance/features/bootstrap/Auth.php +++ b/tests/acceptance/features/bootstrap/Auth.php @@ -37,6 +37,11 @@ trait Auth { */ private $appToken; + /** + * @var array + */ + private $appTokens; + /** * @var boolean */ @@ -74,6 +79,16 @@ public function getAppToken() { return $this->appToken; } + /** + * get the app token that was last generated + * app acceptance tests that have their own step code may need to use this + * + * @return string app token + */ + public function getAppTokens() { + $this->appTokens; + } + /** * @BeforeScenario * @@ -159,6 +174,24 @@ public function userRequestsEndpointsWithBasicAuth($user, $method, TableNode $ta $this->userRequestsEndpointsWithPassword($user, $method, null, $table); } + /** + * @When the user :user requests these endpoints with :method using the basic auth and generated app password then the status codes should be as listed + * + * @param string $user + * @param string $method + * @param TableNode $table + * + * @return void + */ + public function userRequestsEndpointsWithBasicAuthAndGeneratedPassword($user, $method, TableNode $table) { + foreach ($table->getHash() as $row) { + $body = $row['body'] ?? null; + $this->userRequestsURLWithUsingBasicAuth($user, $row['endpoint'], $method, $this->appToken, $body); + $ocsCode = $row['ocs-code'] ?? null; + $this->verifyStatusCode($ocsCode, $row['http-code'], $row['endpoint']); + } + } + /** * @When user :user requests these endpoints with :method using password :password then the status codes should be as listed * @@ -171,7 +204,8 @@ public function userRequestsEndpointsWithBasicAuth($user, $method, TableNode $ta */ public function userRequestsEndpointsWithPassword($user, $method, $password, TableNode $table) { foreach ($table->getHash() as $row) { - $this->userRequestsURLWithUsingBasicAuth($user, $row['endpoint'], $method, $password); + $body = $row['body'] ?? null; + $this->userRequestsURLWithUsingBasicAuth($user, $row['endpoint'], $method, $password, $body); $this->verifyStatusCode($row['ocs-code'], $row['http-code'], $row['endpoint']); } } @@ -254,7 +288,8 @@ public function userRequestsTheseEndpointsUsingNewBrowserSession($method, TableN public function userRequestsEndpointsUsingTheGeneratedAppPassword($method, TableNode $table) { foreach ($table->getHash() as $row) { $this->userRequestsURLWithUsingAppPassword($row['endpoint'], $method); - $this->verifyStatusCode($row['ocs-code'], $row['http-code'], $row['endpoint']); + $ocsCode = $row['ocs-code'] ?? null; + $this->verifyStatusCode($ocsCode, $row['http-code'], $row['endpoint']); } } @@ -312,8 +347,30 @@ public function userGeneratesNewAppPasswordNamed($name) { $this->response = HttpRequestHelper::post( $url, null, null, $headers, $body, null, $this->cookieJar ); - $this->appToken - = \json_decode($this->response->getBody()->getContents())->token; + $token = \json_decode($this->response->getBody()->getContents()); + $this->appToken = $token->token; + $this->appTokens[$token->deviceToken->name] + = ["id" => $token->deviceToken->id, "token" => $token->token]; + } + + /** + * Use the private API to generate an app password + * + * @param string $name + * + * @return void + */ + public function userDeletesAppPasswordNamed($name) { + $url = $this->getBaseUrl() . '/index.php/settings/personal/authtokens/' . $this->appTokens[$name]["id"]; + $headers = [ + 'Content-Type' => 'application/x-www-form-urlencoded', + 'OCS-APIREQUEST' => 'true', + 'requesttoken' => $this->requestToken, + 'X-Requested-With' => 'XMLHttpRequest' + ]; + $this->response = HttpRequestHelper::delete( + $url, null, null, $headers, null, null, $this->cookieJar + ); } /** @@ -328,6 +385,18 @@ public function aNewAppPasswordHasBeenGenerated($name) { $this->theHTTPStatusCodeShouldBe(200); } + /** + * @Given the user has deleted the app password named :name + * + * @param string $name + * + * @return void + */ + public function aNewAppPasswordHasBeenDeleted($name) { + $this->userDeletesAppPasswordNamed($name); + $this->theHTTPStatusCodeShouldBe(200); + } + /** * @When user :user generates a new client token using the token API * @Given a new client token for :user has been generated @@ -487,6 +556,19 @@ public function userRequestsURLWithUsingAppPassword($url, $method) { $this->sendRequest($url, $method, 'token ' . $this->appToken); } + /** + * @When the user requests :url with :method using app password named :tokenName + * + * @param string $url + * @param string $method + * @param string $tokenName + * + * @return void + */ + public function theUserRequestsWithUsingAppPasswordNamed($url, $method, $tokenName) { + $this->sendRequest($url, $method, 'token ' . $this->appTokens[$tokenName]['token']); + } + /** * @Given the user has requested :url with :method using the generated app password *