From 7a58a158ef3211f7e7a03c7bbd6893154baad567 Mon Sep 17 00:00:00 2001 From: adam balsam Date: Fri, 22 May 2026 13:32:03 -0400 Subject: [PATCH 1/3] Allow authenticted users to view sso login page --- .../src/Controller/OAuth2Controller.php | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/docroot/modules/custom/acquia_id/src/Controller/OAuth2Controller.php b/docroot/modules/custom/acquia_id/src/Controller/OAuth2Controller.php index a582655ac..3b301f2e1 100644 --- a/docroot/modules/custom/acquia_id/src/Controller/OAuth2Controller.php +++ b/docroot/modules/custom/acquia_id/src/Controller/OAuth2Controller.php @@ -15,8 +15,6 @@ use Drupal\acquia_id\Events\OAuth2AuthorizationEvent; use Drupal\acquia_id\OAuth2\AccessTokenRepository; use Drupal\acquia_id\OAuth2\Provider\AcquiaIdProvider; -use GuzzleHttp\Exception\RequestException; -use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use League\OAuth2\Client\Token\AccessToken; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -40,6 +38,7 @@ public function __construct( private readonly EventDispatcherInterface $eventDispatcher, private readonly AccessTokenRepository $accessTokenRepository, private readonly string $idpLogoutRedirectUri, + private readonly AccountInterface $currentUser, ) { } @@ -53,6 +52,7 @@ public static function create(ContainerInterface $container): self { $container->get('event_dispatcher'), $container->get('acquia_id.oauth2.access_token_repository'), $container->getParameter('acquia_id.idp_logout_redirect_uri'), + $container->get('current_user'), ); } @@ -61,7 +61,23 @@ public static function create(ContainerInterface $container): self { * * @link https://oauth.net/2/pkce/ */ - public function __invoke(Request $request): RedirectResponse { + public function __invoke(Request $request): RedirectResponse|array { + if (!$this->currentUser->isAnonymous()) { + $token = NULL; + try { + $token = $this->accessTokenRepository->get((int) $this->currentUser->id()); + } + catch (\Exception) { + } + if ($token !== NULL) { + $destination = $request->query->get('destination', ''); + $url = $destination ? Url::fromUserInput($destination) : Url::fromRoute(''); + return [ + '#markup' => '

' . $this->t('You are already logged in.') . '

' . $this->t('Continue') . '

', + ]; + } + } + // Check if this is a subrequest being made on access denied exception. // @see \Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase::onException(). if ($request->attributes->has('exception')) { @@ -135,17 +151,7 @@ public function __invoke(Request $request): RedirectResponse { * Checks access for the SSO route. */ public function access(AccountInterface $account): AccessResultInterface { - $token = NULL; - try { - $token = $this->accessTokenRepository->get((int) $account->id()); - } - catch (IdentityProviderException) { - return AccessResult::allowed(); - } - catch (RequestException) { - } - - return AccessResult::allowedIf($account->isAnonymous() || $token === NULL); + return AccessResult::allowed(); } private function accessDeniedRedirect(string $logMessage = 'Access denied'): RedirectResponse { From 983abd571c3d6898bdfedd4c168255930b62b7c9 Mon Sep 17 00:00:00 2001 From: adam balsam Date: Fri, 22 May 2026 13:42:28 -0400 Subject: [PATCH 2/3] Change test expectations --- .../tests/src/Kernel/Controller/OAuth2ControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docroot/modules/custom/acquia_id/tests/src/Kernel/Controller/OAuth2ControllerTest.php b/docroot/modules/custom/acquia_id/tests/src/Kernel/Controller/OAuth2ControllerTest.php index 4b3c987af..9379a7c97 100644 --- a/docroot/modules/custom/acquia_id/tests/src/Kernel/Controller/OAuth2ControllerTest.php +++ b/docroot/modules/custom/acquia_id/tests/src/Kernel/Controller/OAuth2ControllerTest.php @@ -192,7 +192,7 @@ public function testSsoRouteAccessAuthenticatedWithoutTokenAllowed(): void { $this->assertTrue($result); } - public function testSsoRouteAccessAuthenticatedWithTokenDenied(): void { + public function testSsoRouteAccessAuthenticatedWithToken(): void { $access_manager = $this->container->get('access_manager'); $user = $this->setUpCurrentUser(); @@ -208,7 +208,7 @@ public function testSsoRouteAccessAuthenticatedWithTokenDenied(): void { ]); $result = $access_manager->checkNamedRoute('acquia_id.sso', [], $user); - $this->assertFalse($result); + $this->assertTrue($result); } /** From 17fa0f4893e768e578490de969af5b9cf9865aec Mon Sep 17 00:00:00 2001 From: adam balsam Date: Tue, 26 May 2026 09:45:41 -0400 Subject: [PATCH 3/3] Address feedback --- .../src/Controller/OAuth2Controller.php | 9 ++-- .../Controller/OAuth2ControllerTest.php | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/docroot/modules/custom/acquia_id/src/Controller/OAuth2Controller.php b/docroot/modules/custom/acquia_id/src/Controller/OAuth2Controller.php index 3b301f2e1..d014bc37e 100644 --- a/docroot/modules/custom/acquia_id/src/Controller/OAuth2Controller.php +++ b/docroot/modules/custom/acquia_id/src/Controller/OAuth2Controller.php @@ -62,7 +62,8 @@ public static function create(ContainerInterface $container): self { * @link https://oauth.net/2/pkce/ */ public function __invoke(Request $request): RedirectResponse|array { - if (!$this->currentUser->isAnonymous()) { + $isCallback = $request->query->has('code') || $request->query->has('state') || $request->query->has('error'); + if (!$isCallback && !$this->currentUser->isAnonymous()) { $token = NULL; try { $token = $this->accessTokenRepository->get((int) $this->currentUser->id()); @@ -71,9 +72,11 @@ public function __invoke(Request $request): RedirectResponse|array { } if ($token !== NULL) { $destination = $request->query->get('destination', ''); - $url = $destination ? Url::fromUserInput($destination) : Url::fromRoute(''); + if ($destination) { + return new RedirectResponse(Url::fromUserInput($destination)->toString(), Response::HTTP_SEE_OTHER); + } return [ - '#markup' => '

' . $this->t('You are already logged in.') . '

' . $this->t('Continue') . '

', + '#markup' => '

' . $this->t('You are already logged in.') . '

' . $this->t('Continue') . '

', ]; } } diff --git a/docroot/modules/custom/acquia_id/tests/src/Kernel/Controller/OAuth2ControllerTest.php b/docroot/modules/custom/acquia_id/tests/src/Kernel/Controller/OAuth2ControllerTest.php index 9379a7c97..3130611f7 100644 --- a/docroot/modules/custom/acquia_id/tests/src/Kernel/Controller/OAuth2ControllerTest.php +++ b/docroot/modules/custom/acquia_id/tests/src/Kernel/Controller/OAuth2ControllerTest.php @@ -211,6 +211,51 @@ public function testSsoRouteAccessAuthenticatedWithToken(): void { $this->assertTrue($result); } + public function testAuthenticatedWithTokenShowsAlreadyLoggedIn(): void { + $user = $this->setUpCurrentUser(); + + $token = new AccessToken([ + 'access_token' => 'VALID_ACCESS_TOKEN', + 'expires' => time() + 3600, + ]); + $this->container->get('user.data') + ->set('acquia_id', $user->id(), 'acquia_id_access_token', [ + 'access_token' => $token, + 'timestamp' => time(), + ]); + + $response = $this->doRequest( + Request::create(Url::fromRoute('acquia_id.sso')->toString()), + ); + + $this->assertSame(Response::HTTP_OK, $response->getStatusCode()); + $this->assertStringContainsString('You are already logged in.', $response->getContent()); + $this->assertStringContainsString('Continue', $response->getContent()); + } + + public function testAuthenticatedWithTokenAndDestinationRedirects(): void { + $user = $this->setUpCurrentUser(); + + $token = new AccessToken([ + 'access_token' => 'VALID_ACCESS_TOKEN', + 'expires' => time() + 3600, + ]); + $this->container->get('user.data') + ->set('acquia_id', $user->id(), 'acquia_id_access_token', [ + 'access_token' => $token, + 'timestamp' => time(), + ]); + + $response = $this->doRequest( + Request::create(Url::fromRoute('acquia_id.sso', [], [ + 'query' => ['destination' => '/admin'], + ])->toString()), + ); + + $this->assertSame(Response::HTTP_SEE_OTHER, $response->getStatusCode()); + $this->assertStringContainsString('/admin', $response->headers->get('Location')); + } + /** * Makes an HTTP request through the kernel. */