33namespace Yeebase \TwoFactorAuthentication \Http ;
44
55use Neos \Flow \Annotations as Flow ;
6- use Neos \Flow \Http \Component \ComponentChain ;
7- use Neos \Flow \Http \Component \ComponentContext ;
8- use Neos \Flow \Http \Component \ComponentInterface ;
9- use Neos \Flow \Http \Request as HttpRequest ;
106use Neos \Flow \Mvc \ActionRequest ;
117use Neos \Flow \Mvc \Routing \UriBuilder ;
8+ use Psr \Http \Message \ResponseInterface ;
9+ use Psr \Http \Message \ServerRequestInterface ;
10+ use Psr \Http \Server \MiddlewareInterface ;
11+ use Psr \Http \Server \RequestHandlerInterface ;
12+ use GuzzleHttp \Psr7 \Response ;
13+ use Yeebase \TwoFactorAuthentication \Error \SecondFactorLoginException ;
14+ use Yeebase \TwoFactorAuthentication \Error \SecondFactorSetupException ;
1215
1316/**
1417 * A HTTP component that redirects to the configured 2FA login/setup routes if requested
1518 */
16- final class RedirectComponent implements ComponentInterface
19+ final class RedirectMiddleware implements MiddlewareInterface
1720{
1821 public const REDIRECT_LOGIN = 'login ' ;
1922 public const REDIRECT_SETUP = 'setup ' ;
@@ -30,45 +33,46 @@ final class RedirectComponent implements ComponentInterface
3033 */
3134 protected $ setupRouteValue ;
3235
33- public function handle ( ComponentContext $ componentContext )
36+ public function process ( ServerRequestInterface $ request , RequestHandlerInterface $ next ): ResponseInterface
3437 {
35- $ redirectTarget = $ componentContext -> getParameter ( static ::class, ' redirect ' );
36- if ( $ redirectTarget === null ) {
37- return ;
38- }
39- if ( $ redirectTarget === self :: REDIRECT_LOGIN ) {
40- $ this -> redirectToLogin ( $ componentContext );
41- } elseif ( $ redirectTarget === self :: REDIRECT_SETUP ) {
42- $ this -> redirectToSetup ( $ componentContext );
43- } else {
44- throw new \ RuntimeException ( sprintf ( ' Invalid redirect target "%s" ' , $ redirectTarget ), 1568189192 );
38+ try {
39+ $ response = $ next -> handle ( $ request );
40+ } catch ( \ Exception $ exception ) {
41+ if ( $ exception instanceof SecondFactorLoginException || $ exception -> getPrevious () instanceof SecondFactorLoginException) {
42+ return $ this -> redirectToLogin ( $ request );
43+ } elseif ( $ exception instanceof SecondFactorSetupException || $ exception -> getPrevious () instanceof SecondFactorSetupException) {
44+ return $ this -> redirectToSetup ( $ request );
45+ } else {
46+ throw $ exception ;
47+ }
4548 }
49+ return $ response ;
4650 }
4751
4852 /**
4953 * Triggers a redirect to the 2FA login route configured at routes.login or throws an exception if the configuration is missing/incorrect
5054 */
51- private function redirectToLogin (ComponentContext $ componentContext ): void
55+ private function redirectToLogin (ServerRequestInterface $ request ): ResponseInterface
5256 {
5357 try {
5458 $ this ->validateRouteValues ($ this ->loginRouteValues );
5559 } catch (\InvalidArgumentException $ exception ) {
5660 throw new \RuntimeException ('Missing/invalid routes.login configuration: ' . $ exception ->getMessage (), 1550660144 , $ exception );
5761 }
58- $ this ->redirect ($ componentContext , $ this ->loginRouteValues );
62+ return $ this ->redirect ($ request , $ this ->loginRouteValues );
5963 }
6064
6165 /**
6266 * Triggers a redirect to the 2FA setup route configured at routes.setup or throws an exception if the configuration is missing/incorrect
6367 */
64- private function redirectToSetup (ComponentContext $ componentContext ): void
68+ private function redirectToSetup (ServerRequestInterface $ request ): ResponseInterface
6569 {
6670 try {
6771 $ this ->validateRouteValues ($ this ->setupRouteValue );
6872 } catch (\InvalidArgumentException $ exception ) {
6973 throw new \RuntimeException ('Missing/invalid routes.setup configuration: ' . $ exception ->getMessage (), 1550660178 , $ exception );
7074 }
71- $ this ->redirect ($ componentContext , $ this ->setupRouteValue );
75+ return $ this ->redirect ($ request , $ this ->setupRouteValue );
7276 }
7377
7478 private function validateRouteValues (array $ routeValues ): void
@@ -81,16 +85,13 @@ private function validateRouteValues(array $routeValues): void
8185 }
8286 }
8387
84- private function redirect (ComponentContext $ componentContext , array $ routeValues ): void
88+ private function redirect (ServerRequestInterface $ httpRequest , array $ routeValues ): ResponseInterface
8589 {
86- /** @var HttpRequest $httpRequest */
87- $ httpRequest = $ componentContext ->getHttpRequest ();
88- $ actionRequest = new ActionRequest ($ httpRequest );
90+ $ actionRequest = ActionRequest::fromHttpRequest ($ httpRequest );
8991 $ uriBuilder = new UriBuilder ();
9092 $ uriBuilder ->setRequest ($ actionRequest );
9193 $ redirectUrl = $ uriBuilder ->setCreateAbsoluteUri (true )->setFormat ('html ' )->build ($ routeValues );
9294
93- $ componentContext ->replaceHttpResponse ($ componentContext ->getHttpResponse ()->withStatus (303 )->withHeader ('Location ' , $ redirectUrl ));
94- $ componentContext ->setParameter (ComponentChain::class, 'cancel ' , true );
95+ return (new Response ())->withStatus (303 )->withHeader ('Location ' , $ redirectUrl );
9596 }
9697}
0 commit comments