diff options
author | Igor Scheller <igor.scheller@igorshp.de> | 2018-09-03 15:33:13 +0100 |
---|---|---|
committer | msquare <msquare@notrademark.de> | 2018-11-21 19:24:36 +0100 |
commit | 23c0fae36fb8159bcf8b95bae98555201146457e (patch) | |
tree | 6a169114a47391adb1da701f630bb27d73e925d2 /src/Middleware | |
parent | 8236989be066c51c5f57884bcc42dbc387794651 (diff) |
Added csrf middleware
Diffstat (limited to 'src/Middleware')
-rw-r--r-- | src/Middleware/VerifyCsrfToken.php | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/Middleware/VerifyCsrfToken.php b/src/Middleware/VerifyCsrfToken.php new file mode 100644 index 00000000..cc0c1fbc --- /dev/null +++ b/src/Middleware/VerifyCsrfToken.php @@ -0,0 +1,90 @@ +<?php + +namespace Engelsystem\Middleware; + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Symfony\Component\HttpFoundation\Session\SessionInterface; + +class VerifyCsrfToken implements MiddlewareInterface +{ + /** @var SessionInterface */ + protected $session; + + /** + * @param SessionInterface $session + */ + public function __construct(SessionInterface $session) + { + $this->session = $session; + } + + /** + * Verify csrf tokens + * + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $handler + * @return ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + if ( + $this->isReading($request) + || $this->tokensMatch($request) + ) { + return $handler->handle($request); + } + + return $this->notAuthorizedResponse(); + } + + /** + * @param ServerRequestInterface $request + * @return bool + */ + protected function isReading(ServerRequestInterface $request): bool + { + return in_array( + $request->getMethod(), + ['GET', 'HEAD', 'OPTIONS'] + ); + } + + /** + * @param ServerRequestInterface $request + * @return bool + */ + protected function tokensMatch(ServerRequestInterface $request): bool + { + $token = null; + $body = $request->getParsedBody(); + $header = $request->getHeader('X-CSRF-TOKEN'); + + if (is_array($body) && isset($body['_token'])) { + $token = $body['_token']; + } + + if (!empty($header)) { + $header = array_shift($header); + } + + $token = $token ?: $header; + $sessionToken = $this->session->get('_token'); + + return is_string($token) + && is_string($sessionToken) + && hash_equals($sessionToken, $token); + } + + /** + * @return ResponseInterface + * @codeCoverageIgnore + */ + protected function notAuthorizedResponse(): ResponseInterface + { + // The 419 code is used as "Page Expired" to differentiate from a 401 (not authorized) + return response()->withStatus(419, 'Authentication Token Mismatch'); + } +} |