ApiMiddlewareTest.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <?php
  2. namespace Shaarli\Api;
  3. use Slim\Container;
  4. use Slim\Http\Environment;
  5. use Slim\Http\Request;
  6. use Slim\Http\Response;
  7. /**
  8. * Class ApiMiddlewareTest
  9. *
  10. * Test the REST API Slim Middleware.
  11. *
  12. * Note that we can't test a valid use case here, because the middleware
  13. * needs to call a valid controller/action during its execution.
  14. *
  15. * @package Api
  16. */
  17. class ApiMiddlewareTest extends \PHPUnit_Framework_TestCase
  18. {
  19. /**
  20. * @var string datastore to test write operations
  21. */
  22. protected static $testDatastore = 'sandbox/datastore.php';
  23. /**
  24. * @var \ConfigManager instance
  25. */
  26. protected $conf;
  27. /**
  28. * @var \ReferenceLinkDB instance.
  29. */
  30. protected $refDB = null;
  31. /**
  32. * @var Container instance.
  33. */
  34. protected $container;
  35. /**
  36. * Before every test, instantiate a new Api with its config, plugins and links.
  37. */
  38. public function setUp()
  39. {
  40. $this->conf = new \ConfigManager('tests/utils/config/configJson.json.php');
  41. $this->conf->set('api.secret', 'NapoleonWasALizard');
  42. $this->refDB = new \ReferenceLinkDB();
  43. $this->refDB->write(self::$testDatastore);
  44. $this->container = new Container();
  45. $this->container['conf'] = $this->conf;
  46. }
  47. /**
  48. * After every test, remove the test datastore.
  49. */
  50. public function tearDown()
  51. {
  52. @unlink(self::$testDatastore);
  53. }
  54. /**
  55. * Invoke the middleware with the API disabled:
  56. * should return a 401 error Unauthorized.
  57. */
  58. public function testInvokeMiddlewareApiDisabled()
  59. {
  60. $this->conf->set('api.enabled', false);
  61. $mw = new ApiMiddleware($this->container);
  62. $env = Environment::mock([
  63. 'REQUEST_METHOD' => 'GET',
  64. 'REQUEST_URI' => '/echo',
  65. ]);
  66. $request = Request::createFromEnvironment($env);
  67. $response = new Response();
  68. /** @var Response $response */
  69. $response = $mw($request, $response, null);
  70. $this->assertEquals(401, $response->getStatusCode());
  71. $body = json_decode((string) $response->getBody());
  72. $this->assertEquals('Not authorized', $body);
  73. }
  74. /**
  75. * Invoke the middleware with the API disabled in debug mode:
  76. * should return a 401 error Unauthorized - with a specific message and a stacktrace.
  77. */
  78. public function testInvokeMiddlewareApiDisabledDebug()
  79. {
  80. $this->conf->set('api.enabled', false);
  81. $this->conf->set('dev.debug', true);
  82. $mw = new ApiMiddleware($this->container);
  83. $env = Environment::mock([
  84. 'REQUEST_METHOD' => 'GET',
  85. 'REQUEST_URI' => '/echo',
  86. ]);
  87. $request = Request::createFromEnvironment($env);
  88. $response = new Response();
  89. /** @var Response $response */
  90. $response = $mw($request, $response, null);
  91. $this->assertEquals(401, $response->getStatusCode());
  92. $body = json_decode((string) $response->getBody());
  93. $this->assertEquals('Not authorized: API is disabled', $body->message);
  94. $this->assertContains('ApiAuthorizationException', $body->stacktrace);
  95. }
  96. /**
  97. * Invoke the middleware without a token (debug):
  98. * should return a 401 error Unauthorized - with a specific message and a stacktrace.
  99. */
  100. public function testInvokeMiddlewareNoTokenProvidedDebug()
  101. {
  102. $this->conf->set('dev.debug', true);
  103. $mw = new ApiMiddleware($this->container);
  104. $env = Environment::mock([
  105. 'REQUEST_METHOD' => 'GET',
  106. 'REQUEST_URI' => '/echo',
  107. ]);
  108. $request = Request::createFromEnvironment($env);
  109. $response = new Response();
  110. /** @var Response $response */
  111. $response = $mw($request, $response, null);
  112. $this->assertEquals(401, $response->getStatusCode());
  113. $body = json_decode((string) $response->getBody());
  114. $this->assertEquals('Not authorized: JWT token not provided', $body->message);
  115. $this->assertContains('ApiAuthorizationException', $body->stacktrace);
  116. }
  117. /**
  118. * Invoke the middleware without a secret set in settings (debug):
  119. * should return a 401 error Unauthorized - with a specific message and a stacktrace.
  120. */
  121. public function testInvokeMiddlewareNoSecretSetDebug()
  122. {
  123. $this->conf->set('dev.debug', true);
  124. $this->conf->set('api.secret', '');
  125. $mw = new ApiMiddleware($this->container);
  126. $env = Environment::mock([
  127. 'REQUEST_METHOD' => 'GET',
  128. 'REQUEST_URI' => '/echo',
  129. 'HTTP_AUTHORIZATION'=> 'Bearer jwt',
  130. ]);
  131. $request = Request::createFromEnvironment($env);
  132. $response = new Response();
  133. /** @var Response $response */
  134. $response = $mw($request, $response, null);
  135. $this->assertEquals(401, $response->getStatusCode());
  136. $body = json_decode((string) $response->getBody());
  137. $this->assertEquals('Not authorized: Token secret must be set in Shaarli\'s administration', $body->message);
  138. $this->assertContains('ApiAuthorizationException', $body->stacktrace);
  139. }
  140. /**
  141. * Invoke the middleware with an invalid JWT token header
  142. */
  143. public function testInvalidJwtAuthHeaderDebug()
  144. {
  145. $this->conf->set('dev.debug', true);
  146. $mw = new ApiMiddleware($this->container);
  147. $env = Environment::mock([
  148. 'REQUEST_METHOD' => 'GET',
  149. 'REQUEST_URI' => '/echo',
  150. 'HTTP_AUTHORIZATION'=> 'PolarBearer jwt',
  151. ]);
  152. $request = Request::createFromEnvironment($env);
  153. $response = new Response();
  154. /** @var Response $response */
  155. $response = $mw($request, $response, null);
  156. $this->assertEquals(401, $response->getStatusCode());
  157. $body = json_decode((string) $response->getBody());
  158. $this->assertEquals('Not authorized: Invalid JWT header', $body->message);
  159. $this->assertContains('ApiAuthorizationException', $body->stacktrace);
  160. }
  161. /**
  162. * Invoke the middleware with an invalid JWT token (debug):
  163. * should return a 401 error Unauthorized - with a specific message and a stacktrace.
  164. *
  165. * Note: specific JWT errors tests are handled in ApiUtilsTest.
  166. */
  167. public function testInvokeMiddlewareInvalidJwtDebug()
  168. {
  169. $this->conf->set('dev.debug', true);
  170. $mw = new ApiMiddleware($this->container);
  171. $env = Environment::mock([
  172. 'REQUEST_METHOD' => 'GET',
  173. 'REQUEST_URI' => '/echo',
  174. 'HTTP_AUTHORIZATION'=> 'Bearer jwt',
  175. ]);
  176. $request = Request::createFromEnvironment($env);
  177. $response = new Response();
  178. /** @var Response $response */
  179. $response = $mw($request, $response, null);
  180. $this->assertEquals(401, $response->getStatusCode());
  181. $body = json_decode((string) $response->getBody());
  182. $this->assertEquals('Not authorized: Malformed JWT token', $body->message);
  183. $this->assertContains('ApiAuthorizationException', $body->stacktrace);
  184. }
  185. }