Auth.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. use GuzzleHttp\Client;
  8. use GuzzleHttp\Cookie\CookieJar;
  9. use GuzzleHttp\Exception\ClientException;
  10. use GuzzleHttp\Exception\ServerException;
  11. require __DIR__ . '/../../vendor/autoload.php';
  12. trait Auth {
  13. /** @var string */
  14. private $unrestrictedClientToken;
  15. /** @var string */
  16. private $restrictedClientToken;
  17. /** @var Client */
  18. private $client;
  19. /** @var string */
  20. private $responseXml;
  21. /** @BeforeScenario */
  22. public function setUpScenario() {
  23. $this->client = new Client();
  24. $this->responseXml = '';
  25. $this->cookieJar = new CookieJar();
  26. }
  27. /**
  28. * @When requesting :url with :method
  29. */
  30. public function requestingWith($url, $method) {
  31. $this->sendRequest($url, $method);
  32. }
  33. private function sendRequest($url, $method, $authHeader = null, $useCookies = false) {
  34. $fullUrl = substr($this->baseUrl, 0, -5) . $url;
  35. try {
  36. if ($useCookies) {
  37. $options = [
  38. 'cookies' => $this->cookieJar,
  39. ];
  40. } else {
  41. $options = [];
  42. }
  43. if ($authHeader) {
  44. $options['headers'] = [
  45. 'Authorization' => $authHeader
  46. ];
  47. }
  48. $options['headers']['OCS_APIREQUEST'] = 'true';
  49. $options['headers']['requesttoken'] = $this->requestToken;
  50. $this->response = $this->client->request($method, $fullUrl, $options);
  51. } catch (ClientException $ex) {
  52. $this->response = $ex->getResponse();
  53. } catch (ServerException $ex) {
  54. $this->response = $ex->getResponse();
  55. }
  56. }
  57. /**
  58. * @When the CSRF token is extracted from the previous response
  59. */
  60. public function theCsrfTokenIsExtractedFromThePreviousResponse() {
  61. $this->requestToken = substr(preg_replace('/(.*)data-requesttoken="(.*)">(.*)/sm', '\2', $this->response->getBody()->getContents()), 0, 89);
  62. }
  63. /**
  64. * @param bool $loginViaWeb
  65. * @return object
  66. */
  67. private function createClientToken($loginViaWeb = true) {
  68. if ($loginViaWeb) {
  69. $this->loggingInUsingWebAs('user0');
  70. }
  71. $fullUrl = substr($this->baseUrl, 0, -5) . '/index.php/settings/personal/authtokens';
  72. $client = new Client();
  73. $options = [
  74. 'auth' => [
  75. 'user0',
  76. $loginViaWeb ? '123456' : $this->restrictedClientToken,
  77. ],
  78. 'form_params' => [
  79. 'requesttoken' => $this->requestToken,
  80. 'name' => md5(microtime()),
  81. ],
  82. 'cookies' => $this->cookieJar,
  83. ];
  84. try {
  85. $this->response = $client->request('POST', $fullUrl, $options);
  86. } catch (\GuzzleHttp\Exception\ServerException $e) {
  87. $this->response = $e->getResponse();
  88. }
  89. return json_decode($this->response->getBody()->getContents());
  90. }
  91. /**
  92. * @Given a new restricted client token is added
  93. */
  94. public function aNewRestrictedClientTokenIsAdded() {
  95. $tokenObj = $this->createClientToken();
  96. $newCreatedTokenId = $tokenObj->deviceToken->id;
  97. $fullUrl = substr($this->baseUrl, 0, -5) . '/index.php/settings/personal/authtokens/' . $newCreatedTokenId;
  98. $client = new Client();
  99. $options = [
  100. 'auth' => ['user0', '123456'],
  101. 'headers' => [
  102. 'requesttoken' => $this->requestToken,
  103. ],
  104. 'json' => [
  105. 'name' => md5(microtime()),
  106. 'scope' => [
  107. 'filesystem' => false,
  108. ],
  109. ],
  110. 'cookies' => $this->cookieJar,
  111. ];
  112. $this->response = $client->request('PUT', $fullUrl, $options);
  113. $this->restrictedClientToken = $tokenObj->token;
  114. }
  115. /**
  116. * @Given a new unrestricted client token is added
  117. */
  118. public function aNewUnrestrictedClientTokenIsAdded() {
  119. $this->unrestrictedClientToken = $this->createClientToken()->token;
  120. }
  121. /**
  122. * @When a new unrestricted client token is added using restricted basic token auth
  123. */
  124. public function aNewUnrestrictedClientTokenIsAddedUsingRestrictedBasicTokenAuth() {
  125. $this->createClientToken(false);
  126. }
  127. /**
  128. * @When requesting :url with :method using basic auth
  129. *
  130. * @param string $url
  131. * @param string $method
  132. */
  133. public function requestingWithBasicAuth($url, $method) {
  134. $this->sendRequest($url, $method, 'basic ' . base64_encode('user0:123456'));
  135. }
  136. /**
  137. * @When requesting :url with :method using unrestricted basic token auth
  138. *
  139. * @param string $url
  140. * @param string $method
  141. */
  142. public function requestingWithUnrestrictedBasicTokenAuth($url, $method) {
  143. $this->sendRequest($url, $method, 'basic ' . base64_encode('user0:' . $this->unrestrictedClientToken), true);
  144. }
  145. /**
  146. * @When requesting :url with :method using restricted basic token auth
  147. *
  148. * @param string $url
  149. * @param string $method
  150. */
  151. public function requestingWithRestrictedBasicTokenAuth($url, $method) {
  152. $this->sendRequest($url, $method, 'basic ' . base64_encode('user0:' . $this->restrictedClientToken), true);
  153. }
  154. /**
  155. * @When requesting :url with :method using an unrestricted client token
  156. *
  157. * @param string $url
  158. * @param string $method
  159. */
  160. public function requestingWithUsingAnUnrestrictedClientToken($url, $method) {
  161. $this->sendRequest($url, $method, 'Bearer ' . $this->unrestrictedClientToken);
  162. }
  163. /**
  164. * @When requesting :url with :method using a restricted client token
  165. *
  166. * @param string $url
  167. * @param string $method
  168. */
  169. public function requestingWithUsingARestrictedClientToken($url, $method) {
  170. $this->sendRequest($url, $method, 'Bearer ' . $this->restrictedClientToken);
  171. }
  172. /**
  173. * @When requesting :url with :method using browser session
  174. *
  175. * @param string $url
  176. * @param string $method
  177. */
  178. public function requestingWithBrowserSession($url, $method) {
  179. $this->sendRequest($url, $method, null, true);
  180. }
  181. /**
  182. * @Given a new browser session is started
  183. *
  184. * @param bool $remember
  185. */
  186. public function aNewBrowserSessionIsStarted($remember = false) {
  187. $loginUrl = substr($this->baseUrl, 0, -5) . '/login';
  188. // Request a new session and extract CSRF token
  189. $client = new Client();
  190. $response = $client->get($loginUrl, [
  191. 'cookies' => $this->cookieJar,
  192. ]);
  193. $this->extracRequestTokenFromResponse($response);
  194. // Login and extract new token
  195. $client = new Client();
  196. $response = $client->post(
  197. $loginUrl, [
  198. 'form_params' => [
  199. 'user' => 'user0',
  200. 'password' => '123456',
  201. 'remember_login' => $remember ? '1' : '0',
  202. 'requesttoken' => $this->requestToken,
  203. ],
  204. 'cookies' => $this->cookieJar,
  205. ]
  206. );
  207. $this->extracRequestTokenFromResponse($response);
  208. }
  209. /**
  210. * @Given a new remembered browser session is started
  211. */
  212. public function aNewRememberedBrowserSessionIsStarted() {
  213. $this->aNewBrowserSessionIsStarted(true);
  214. }
  215. /**
  216. * @Given the cookie jar is reset
  217. */
  218. public function theCookieJarIsReset() {
  219. $this->cookieJar = new CookieJar();
  220. }
  221. /**
  222. * @When the session cookie expires
  223. */
  224. public function whenTheSessionCookieExpires() {
  225. $this->cookieJar->clearSessionCookies();
  226. }
  227. }