From 6033fd0c8d2699a129365b8df178a95c07603781 Mon Sep 17 00:00:00 2001 From: catch Date: Wed, 15 Dec 2021 10:26:57 +0000 Subject: [PATCH] Issue #3253889 by BR0kEN, murilohp, longwave: `?check_logged_in=1` causes `TrustedRedirectResponse` to fail --- .../src/Authentication/Provider/Cookie.php | 7 +++ .../user/tests/src/Unit/UserAuthTest.php | 60 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/core/modules/user/src/Authentication/Provider/Cookie.php b/core/modules/user/src/Authentication/Provider/Cookie.php index 0fcac24a0d0..aea58f67ea8 100644 --- a/core/modules/user/src/Authentication/Provider/Cookie.php +++ b/core/modules/user/src/Authentication/Provider/Cookie.php @@ -6,6 +6,7 @@ use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Authentication\AuthenticationProviderInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Messenger\MessengerInterface; +use Drupal\Core\Routing\TrustedRedirectResponse; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\UserSession; use Drupal\Core\Session\SessionConfigurationInterface; @@ -136,6 +137,12 @@ class Cookie implements AuthenticationProviderInterface, EventSubscriberInterfac if (!empty($options['#fragment'])) { $url .= '#' . $options['#fragment']; } + // In the case of trusted redirect, we have to update the list of + // trusted URLs because here we've just modified its target URL + // which is in the list. + if ($response instanceof TrustedRedirectResponse) { + $response->setTrustedTargetUrl($url); + } $response->setTargetUrl($url); } } diff --git a/core/modules/user/tests/src/Unit/UserAuthTest.php b/core/modules/user/tests/src/Unit/UserAuthTest.php index 2ac6d0c05c1..10526a40392 100644 --- a/core/modules/user/tests/src/Unit/UserAuthTest.php +++ b/core/modules/user/tests/src/Unit/UserAuthTest.php @@ -3,8 +3,15 @@ namespace Drupal\Tests\user\Unit; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Routing\RequestContext; +use Drupal\Core\Routing\TrustedRedirectResponse; use Drupal\Tests\UnitTestCase; +use Drupal\user\Authentication\Provider\Cookie; use Drupal\user\UserAuth; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpKernel\Event\ResponseEvent; /** * @coversDefaultClass \Drupal\user\UserAuth @@ -220,4 +227,57 @@ class UserAuthTest extends UnitTestCase { $this->assertSame(1, $this->userAuth->authenticate($this->username, $this->password)); } + /** + * Tests the auth that ends in a redirect from subdomain to TLD. + */ + public function testAddCheckToUrlForTrustedRedirectResponse(): void { + $site_domain = 'site.com'; + $frontend_url = "https://$site_domain"; + $backend_url = "https://api.$site_domain"; + $request = Request::create($backend_url); + $response = new TrustedRedirectResponse($frontend_url); + + $request_context = $this->createMock(RequestContext::class); + $request_context + ->method('getCompleteBaseUrl') + ->willReturn($backend_url); + + $container = new ContainerBuilder(); + $container->set('router.request_context', $request_context); + \Drupal::setContainer($container); + + $session_mock = $this->createMock(SessionInterface::class); + $session_mock + ->expects($this->once()) + ->method('has') + ->with('check_logged_in') + ->willReturn(TRUE); + $session_mock + ->expects($this->once()) + ->method('remove') + ->with('check_logged_in'); + + $event_mock = $this->createMock(ResponseEvent::class); + $event_mock + ->expects($this->once()) + ->method('getResponse') + ->willReturn($response); + $event_mock + ->expects($this->exactly(3)) + ->method('getRequest') + ->willReturn($request); + + $request + ->setSession($session_mock); + + $this + ->getMockBuilder(Cookie::class) + ->disableOriginalConstructor() + ->onlyMethods([]) + ->getMock() + ->addCheckToUrl($event_mock); + + $this->assertSame("$frontend_url?check_logged_in=1", $response->getTargetUrl()); + } + }