HTTPSignatureTest.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. // This file is part of GNU social - https://www.gnu.org/software/social
  3. //
  4. // GNU social is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // GNU social is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * ActivityPub implementation for GNU social
  18. *
  19. * @package GNUsocial
  20. * @author Diogo Cordeiro <diogo@fc.up.pt>
  21. * @copyright 2018-2019 Free Software Foundation, Inc http://www.fsf.org
  22. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  23. * @link http://www.gnu.org/software/social/
  24. */
  25. namespace Tests\Unit;
  26. use Tests\TestCase;
  27. use GuzzleHttp\Client;
  28. use GuzzleHttp\Handler\CurlHandler;
  29. use GuzzleHttp\Handler\MockHandler;
  30. use GuzzleHttp\HandlerStack;
  31. use GuzzleHttp\Middleware;
  32. use GuzzleHttp\Psr7\Request;
  33. use GuzzleHttp\Psr7\Response;
  34. use HttpSignatures\Context;
  35. use HttpSignatures\GuzzleHttpSignatures;
  36. class HTTPSignatureTest extends TestCase
  37. {
  38. /**
  39. * @var Context
  40. */
  41. private $context;
  42. /**
  43. * @var Client
  44. */
  45. private $client;
  46. /**
  47. * @var
  48. */
  49. private $history = [];
  50. public function testLibraryInstalled()
  51. {
  52. $this->assertTrue(class_exists('\GuzzleHttp\Client'));
  53. $this->assertTrue(class_exists('\HttpSignatures\Context'));
  54. $this->assertTrue(class_exists('\HttpSignatures\GuzzleHttpSignatures'));
  55. }
  56. public function setUp()
  57. {
  58. $this->context = new Context([
  59. 'keys' => ['pda' => 'secret'],
  60. 'algorithm' => 'hmac-sha256',
  61. 'headers' => ['(request-target)', 'date'],
  62. ]);
  63. $stack = new HandlerStack();
  64. $stack->setHandler(new MockHandler([
  65. new Response(200, ['Content-Length' => 0]),
  66. ]));
  67. $stack->push(GuzzleHttpSignatures::middlewareFromContext($this->context));
  68. $stack->push(Middleware::history($this->history));
  69. $this->client = new Client(['handler' => $stack]);
  70. }
  71. /**
  72. * test signing a message
  73. */
  74. public function testGuzzleRequestHasExpectedHeaders()
  75. {
  76. $this->client->get('/path?query=123', [
  77. 'headers' => ['date' => 'today', 'accept' => 'llamas']
  78. ]);
  79. // get last request
  80. $message = end($this->history);
  81. /** @var Request $request */
  82. $request = $message['request'];
  83. /** @var Response $response */
  84. $response = $message['request'];
  85. $expectedString = implode(
  86. ',',
  87. [
  88. 'keyId="pda"',
  89. 'algorithm="hmac-sha256"',
  90. 'headers="(request-target) date"',
  91. 'signature="SFlytCGpsqb/9qYaKCQklGDvwgmrwfIERFnwt+yqPJw="',
  92. ]
  93. );
  94. $this->assertEquals(
  95. [$expectedString],
  96. $request->getHeader('Signature')
  97. );
  98. $this->assertEquals(
  99. ['Signature ' . $expectedString],
  100. $request->getHeader('Authorization')
  101. );
  102. }
  103. /**
  104. * test signing a message with a URL that doesn't contain a ?query
  105. */
  106. public function testGuzzleRequestHasExpectedHeaders2()
  107. {
  108. $this->client->get('/path', [
  109. 'headers' => ['date' => 'today', 'accept' => 'llamas']
  110. ]);
  111. // get last request
  112. $message = end($this->history);
  113. /** @var Request $request */
  114. $request = $message['request'];
  115. /** @var Response $response */
  116. $response = $message['request'];
  117. $expectedString = implode(
  118. ',',
  119. [
  120. 'keyId="pda"',
  121. 'algorithm="hmac-sha256"',
  122. 'headers="(request-target) date"',
  123. 'signature="DAtF133khP05pS5Gh8f+zF/UF7mVUojMj7iJZO3Xk4o="',
  124. ]
  125. );
  126. $this->assertEquals(
  127. [$expectedString],
  128. $request->getHeader('Signature')
  129. );
  130. $this->assertEquals(
  131. ['Signature ' . $expectedString],
  132. $request->getHeader('Authorization')
  133. );
  134. }
  135. public function getVerifyGuzzleRequestVectors()
  136. {
  137. return [
  138. /* path, headers */
  139. ['/path?query=123', ['date' => 'today', 'accept' => 'llamas']],
  140. ['/path?z=zebra&a=antelope', ['date' => 'today']],
  141. ];
  142. }
  143. /**
  144. * @dataProvider getVerifyGuzzleRequestVectors
  145. * @param string $path
  146. * @param array $headers
  147. */
  148. public function testVerifyGuzzleRequest($path, $headers)
  149. {
  150. $this->client->get($path, ['headers' => $headers]);
  151. // get last request
  152. $message = end($this->history);
  153. /** @var Request $request */
  154. $request = $message['request'];
  155. /** @var Response $response */
  156. $response = $message['request'];
  157. $this->assertTrue($this->context->verifier()->isValid($request));
  158. }
  159. }