| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- <?php
- declare(strict_types=1);
- namespace App\Tests\Unit\Http;
- use App\Http\CsrfMiddleware;
- use PHPUnit\Framework\TestCase;
- use Psr\Http\Message\ResponseInterface;
- use Psr\Http\Message\ServerRequestInterface;
- use Psr\Http\Server\RequestHandlerInterface;
- use Slim\Psr7\Factory\ResponseFactory;
- use Slim\Psr7\Factory\ServerRequestFactory;
- use Slim\Psr7\Factory\StreamFactory;
- final class CsrfMiddlewareTest extends TestCase
- {
- protected function setUp(): void
- {
- $_SESSION = [];
- }
- public function testGetGeneratesTokenAndPasses(): void
- {
- $mw = new CsrfMiddleware(new ResponseFactory());
- $request = (new ServerRequestFactory())->createServerRequest('GET', '/login');
- $response = $mw->process($request, $this->handler(static function (ServerRequestInterface $req): bool {
- return is_string($req->getAttribute(CsrfMiddleware::ATTR_TOKEN))
- && strlen((string) $req->getAttribute(CsrfMiddleware::ATTR_TOKEN)) === 64;
- }));
- self::assertSame(200, $response->getStatusCode());
- self::assertNotEmpty($_SESSION[CsrfMiddleware::SESSION_KEY]);
- }
- public function testPostWithoutTokenIs403(): void
- {
- $mw = new CsrfMiddleware(new ResponseFactory());
- $request = (new ServerRequestFactory())->createServerRequest('POST', '/login/local');
- $response = $mw->process($request, $this->handler(static fn () => true));
- self::assertSame(403, $response->getStatusCode());
- }
- public function testPostWithMatchingFormFieldPasses(): void
- {
- $mw = new CsrfMiddleware(new ResponseFactory());
- $_SESSION[CsrfMiddleware::SESSION_KEY] = 'fixed-token';
- $request = (new ServerRequestFactory())
- ->createServerRequest('POST', '/login/local')
- ->withParsedBody(['csrf_token' => 'fixed-token', 'username' => 'a']);
- $response = $mw->process($request, $this->handler(static fn () => true));
- self::assertSame(200, $response->getStatusCode());
- }
- public function testPostWithMatchingHeaderPasses(): void
- {
- $mw = new CsrfMiddleware(new ResponseFactory());
- $_SESSION[CsrfMiddleware::SESSION_KEY] = 'fixed-token';
- $request = (new ServerRequestFactory())
- ->createServerRequest('POST', '/api/x')
- ->withHeader('X-CSRF-Token', 'fixed-token');
- $response = $mw->process($request, $this->handler(static fn () => true));
- self::assertSame(200, $response->getStatusCode());
- }
- public function testPostWithWrongTokenIs403(): void
- {
- $mw = new CsrfMiddleware(new ResponseFactory());
- $_SESSION[CsrfMiddleware::SESSION_KEY] = 'fixed-token';
- $request = (new ServerRequestFactory())
- ->createServerRequest('POST', '/login/local')
- ->withParsedBody(['csrf_token' => 'wrong-token']);
- $response = $mw->process($request, $this->handler(static fn () => true));
- self::assertSame(403, $response->getStatusCode());
- }
- /**
- * @param callable(ServerRequestInterface): bool $assert
- */
- private function handler(callable $assert): RequestHandlerInterface
- {
- return new class ($assert) implements RequestHandlerInterface {
- /** @var callable(ServerRequestInterface): bool */
- private $assert;
- public function __construct(callable $assert)
- {
- $this->assert = $assert;
- }
- public function handle(ServerRequestInterface $request): ResponseInterface
- {
- $ok = ($this->assert)($request);
- $factory = new ResponseFactory();
- $response = $factory->createResponse($ok ? 200 : 418);
- $stream = (new StreamFactory())->createStream('OK');
- return $response->withBody($stream);
- }
- };
- }
- }
|