-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathRedirectMiddleware.php
More file actions
97 lines (87 loc) · 3.76 KB
/
RedirectMiddleware.php
File metadata and controls
97 lines (87 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php
declare(strict_types=1);
namespace Yeebase\TwoFactorAuthentication\Http;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\ActionRequest;
use Neos\Flow\Mvc\Routing\UriBuilder;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use GuzzleHttp\Psr7\Response;
use Yeebase\TwoFactorAuthentication\Error\SecondFactorLoginException;
use Yeebase\TwoFactorAuthentication\Error\SecondFactorSetupException;
/**
* A HTTP component that redirects to the configured 2FA login/setup routes if requested
*/
final class RedirectMiddleware implements MiddlewareInterface
{
public const REDIRECT_LOGIN = 'login';
public const REDIRECT_SETUP = 'setup';
/**
* @Flow\InjectConfiguration(path="routes.login")
* @var array
*/
protected $loginRouteValues;
/**
* @Flow\InjectConfiguration(path="routes.setup")
* @var array
*/
protected $setupRouteValue;
public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
{
try {
$response = $next->handle($request);
} catch (\Exception $exception) {
if ($exception instanceof SecondFactorLoginException || $exception->getPrevious() instanceof SecondFactorLoginException) {
return $this->redirectToLogin($request);
} elseif ($exception instanceof SecondFactorSetupException || $exception->getPrevious() instanceof SecondFactorSetupException) {
return $this->redirectToSetup($request);
} else {
throw $exception;
}
}
return $response;
}
/**
* Triggers a redirect to the 2FA login route configured at routes.login or throws an exception if the configuration is missing/incorrect
*/
private function redirectToLogin(ServerRequestInterface $request): ResponseInterface
{
try {
$this->validateRouteValues($this->loginRouteValues);
} catch (\InvalidArgumentException $exception) {
throw new \RuntimeException('Missing/invalid routes.login configuration: ' . $exception->getMessage(), 1550660144, $exception);
}
return $this->redirect($request, $this->loginRouteValues);
}
/**
* Triggers a redirect to the 2FA setup route configured at routes.setup or throws an exception if the configuration is missing/incorrect
*/
private function redirectToSetup(ServerRequestInterface $request): ResponseInterface
{
try {
$this->validateRouteValues($this->setupRouteValue);
} catch (\InvalidArgumentException $exception) {
throw new \RuntimeException('Missing/invalid routes.setup configuration: ' . $exception->getMessage(), 1550660178, $exception);
}
return $this->redirect($request, $this->setupRouteValue);
}
private function validateRouteValues(array $routeValues): void
{
$requiredRouteValues = ['@package', '@controller', '@action'];
foreach ($requiredRouteValues as $routeValue) {
if (!array_key_exists($routeValue, $routeValues)) {
throw new \InvalidArgumentException(sprintf('Missing "%s" route value', $routeValue), 1550660039);
}
}
}
private function redirect(ServerRequestInterface $httpRequest, array $routeValues): ResponseInterface
{
$actionRequest = ActionRequest::fromHttpRequest($httpRequest);
$uriBuilder = new UriBuilder();
$uriBuilder->setRequest($actionRequest);
$redirectUrl = $uriBuilder->setCreateAbsoluteUri(true)->setFormat('html')->build($routeValues);
return (new Response())->withStatus(303)->withHeader('Location', $redirectUrl);
}
}