Skip to content

Commit 6d1efdd

Browse files
authored
feat(feedback): show bookmark error page for saved WAYF URLs (#2026)
* feat(feedback): show bookmark error page for saved WAYF URLs When the hide_bookmarkable_url feature is enabled, JS replaces the WAYF URL (containing SAMLRequest) with ?feedback=bookmark via history.replaceState. Visiting that bookmarked URL now shows a dedicated error page instead of a generic missing-parameter error. - Add bookmarked-page feedback route and error page - Gate hideBookmarkableUrl JSON config value behind eb.hide_bookmarkable_url flag - Handle ?feedback=bookmark redirect in singleSignOnAction before SAML validation (replaces smelly exception-listener query-param inspection) - Wire Wayf Twig extension to FunctionalTestingFeatureConfiguration in ci env - Add Behat scenarios covering the bookmark redirect and flag toggling Closes #1976 * chore: regenerate reference.php type stubs
1 parent 660371b commit 6d1efdd

14 files changed

Lines changed: 125 additions & 56 deletions

File tree

config/reference.php

Lines changed: 50 additions & 50 deletions
Large diffs are not rendered by default.

config/services/ci/controllers.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ services:
5050
- '@OpenConext\EngineBlock\Validator\UnsolicitedSsoRequestValidator'
5151
- '@OpenConext\EngineBlock\Service\AuthenticationStateHelper'
5252
- '@engineblock.functional_testing.fixture.features'
53+
- '@router'
5354

5455
engineblock.functional_test.controller.sbs:
5556
class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\SbsController

config/services/ci/services.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,13 @@ services:
149149
- '@engineblock.functional_testing.fixture.features'
150150
- '%stepup.sfo.override_engine_entityid%'
151151

152+
OpenConext\EngineBlockBundle\Twig\Extensions\Extension\Wayf:
153+
autoconfigure: true
154+
arguments:
155+
- '@request_stack'
156+
- '@translator'
157+
- '@engineblock.functional_testing.fixture.features'
158+
152159
OpenConext\EngineBlockBundle\Twig\Extensions\Extension\FunctionalTestingGlobalSiteNotice:
153160
autoconfigure: true
154161
arguments:

config/services/controllers/authentication.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ services:
2222
- '@OpenConext\EngineBlock\Validator\UnsolicitedSsoRequestValidator'
2323
- '@OpenConext\EngineBlock\Service\AuthenticationStateHelper'
2424
- '@OpenConext\EngineBlockBundle\Configuration\FeatureConfiguration'
25+
- '@router'
2526

2627
OpenConext\EngineBlockBundle\Controller\IndexController:
2728
arguments:

languages/messages.en.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@
234234
'error_authentication_limit_exceeded' => 'Error - too many authentications in progress',
235235
'error_authentication_limit_exceeded_desc' => 'Too many authentications in progress',
236236
'error_no_authentication_request_received' => 'Error - No authentication request received.',
237+
'error_bookmarked_page' => 'Error - This page no longer exists',
238+
'error_bookmarked_page_desc' => 'The page you are trying to visit no longer exists. You probably saved a bookmark, but unfortunately that doesn\'t work. Search for the correct link to the application you want to log in to in order to gain access.',
237239
'error_authn_context_class_ref_blacklisted' => 'Error - AuthnContextClassRef value is not allowed',
238240
'error_authn_context_class_ref_blacklisted_desc' => 'You cannot login because %idpName% sent a value for AuthnContextClassRef that is not allowed. Please contact the service desk of %idpName% to solve this.',
239241
'error_authn_context_class_ref_blacklisted_desc_no_idp_name' => 'You cannot login because your %organisationNoun% sent a value for AuthnContextClassRef that is not allowed. Please contact the service desk of your %organisationNoun% to solve this.',

languages/messages.nl.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@
231231
'error_authentication_limit_exceeded' => 'Fout - teveel onafgeronde authenticaties tegelijkertijd.',
232232
'error_authentication_limit_exceeded_desc' => 'Teveel onafgeronde authenticaties tegelijkertijd.',
233233
'error_no_authentication_request_received' => 'Fout - Geen authenticatie-aanvraag ontvangen.',
234+
'error_bookmarked_page' => 'Fout - Deze pagina bestaat niet meer',
235+
'error_bookmarked_page_desc' => 'De pagina die je probeert te bezoeken bestaat niet meer. Waarschijnlijk heb je de pagina als bladwijzer opgeslagen, maar dat werkt helaas niet. Zoek de juiste link naar de applicatie waarop je wilt inloggen om toegang te krijgen.',
234236
'error_authn_context_class_ref_blacklisted' => 'Fout - Waarde van AuthnContextClassRef is niet toegestaan',
235237
'error_authn_context_class_ref_blacklisted_desc' => 'Je kunt niet inloggen omdat %idpName% een waarde stuurde voor AuthnContextClassRef die niet is toegestaan. Neem contact op met de helpdesk van %idpName% om dit op te lossen.',
236238
'error_authn_context_class_ref_blacklisted_desc_no_idp_name' => 'Je kunt niet inloggen omdat je %organisationNoun% een waarde stuurde voor AuthnContextClassRef die niet is toegestaan. Neem contact op met de helpdesk van je %organisationNoun% om dit op te lossen.',

languages/messages.pt.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@
231231
'error_invalid_mfa_authn_context_class_ref_desc' => '<p>A %idpName% requer segurança adicional para este serviço, por meio de um segundo fator de autenticação (2FA). No entanto, o seu segundo fator de autenticação não pôde ser verificado. Entre em contato com o suporte da %idpName% para validar esta situação.</p>',
232232
'error_invalid_mfa_authn_context_class_ref_desc_no_idp_name' => '<p>A sua %organisationNoun% requer segurança adicional para este serviço, por meio de um segundo fator de autenticação (2FA). No entanto, o seu segundo fator de autenticação não pôde ser verificado. Entre em contato com o suporte da sua %organisationNoun% para validar esta situação.</p>',
233233
'error_no_authentication_request_received' => 'Não foi recebida nenhuma solicitação de autenticação.',
234+
'error_bookmarked_page' => 'Erro - Esta página já não existe',
235+
'error_bookmarked_page_desc' => 'A página que está a tentar visitar já não existe. Provavelmente guardou um marcador, mas infelizmente isso não funciona. Procure o link correto para a aplicação em que pretende iniciar sessão para obter acesso.',
234236
/**
235237
* %1 AttributeName
236238
* %2 Options

src/OpenConext/EngineBlockBundle/Configuration/TestFeatureConfiguration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public function __construct()
4848
$this->setFeature(new Feature('eb.feature_enable_idp_initiated_flow', true));
4949
$this->setFeature(new Feature('eb.stepup.send_user_attributes', true));
5050
$this->setFeature(new Feature('eb.feature_enable_sram_interrupt', true));
51-
$this->setFeature(new Feature('eb.hide_bookmarkable_url', false));
51+
$this->setFeature(new Feature('eb.hide_bookmarkable_url', true));
5252
}
5353

5454
public function setFeature(Feature $feature): void

src/OpenConext/EngineBlockBundle/Controller/FeedbackController.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,15 @@ public function __construct(
153153
],
154154
methods: ['GET']
155155
)]
156+
#[Route(
157+
path: '/authentication/feedback/bookmarked-page',
158+
name: 'authentication_feedback_bookmarked_page',
159+
defaults: [
160+
'pageIdentifier' => 'bookmarked-page',
161+
'statusCode' => 400
162+
],
163+
methods: ['GET']
164+
)]
156165
public function feedbackAction(string $pageIdentifier, int $statusCode): Response
157166
{
158167
return new Response(

src/OpenConext/EngineBlockBundle/Controller/IdentityProviderController.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,22 @@
2626
use OpenConext\EngineBlockBridge\ResponseFactory;
2727
use OpenConext\EngineBlockBundle\Configuration\FeatureConfigurationInterface;
2828
use Psr\Log\LoggerInterface;
29+
use Symfony\Component\HttpFoundation\RedirectResponse;
2930
use Symfony\Component\HttpFoundation\Request;
3031
use Symfony\Component\HttpFoundation\Response;
3132
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
3233
use Symfony\Component\Routing\Attribute\Route;
34+
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
3335
use Twig\Environment;
3436

3537
/**
3638
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) Due to the compatibility requirements
39+
* @SuppressWarnings(PHPMD.ExcessiveParameterList) Due to the compatibility requirements
3740
*/
3841
class IdentityProviderController implements AuthenticationLoopThrottlingController
3942
{
43+
private const FEEDBACK_BOOKMARK = 'bookmark';
44+
4045
/**
4146
* @var EngineBlock_ApplicationSingleton
4247
*/
@@ -82,6 +87,11 @@ class IdentityProviderController implements AuthenticationLoopThrottlingControll
8287
*/
8388
private $featureConfiguration;
8489

90+
/**
91+
* @var UrlGeneratorInterface
92+
*/
93+
private $urlGenerator;
94+
8595
public function __construct(
8696
EngineBlock_ApplicationSingleton $engineBlockApplicationSingleton,
8797
Environment $twig,
@@ -91,7 +101,8 @@ public function __construct(
91101
RequestValidator $bindingValidator,
92102
RequestValidator $unsolicitedRequestValidator,
93103
AuthenticationStateHelperInterface $authenticationStateHelper,
94-
FeatureConfigurationInterface $featureConfiguration
104+
FeatureConfigurationInterface $featureConfiguration,
105+
UrlGeneratorInterface $urlGenerator
95106
) {
96107
$this->engineBlockApplicationSingleton = $engineBlockApplicationSingleton;
97108
$this->twig = $twig;
@@ -102,6 +113,7 @@ public function __construct(
102113
$this->unsolicitedRequestValidator = $unsolicitedRequestValidator;
103114
$this->authenticationStateHelper = $authenticationStateHelper;
104115
$this->featureConfiguration = $featureConfiguration;
116+
$this->urlGenerator = $urlGenerator;
105117
}
106118

107119
/**
@@ -122,6 +134,12 @@ public function __construct(
122134
#[Route(path: '/authentication/idp/single-sign-on/{idpHash}', name: 'authentication_idp_sso_idphash', methods: ['GET', 'POST'])]
123135
public function singleSignOnAction(Request $request, ?string $keyId = null, ?string $idpHash = null)
124136
{
137+
if ($request->query->get('feedback') === self::FEEDBACK_BOOKMARK) {
138+
return new RedirectResponse(
139+
$this->urlGenerator->generate('authentication_feedback_bookmarked_page', [], UrlGeneratorInterface::ABSOLUTE_PATH)
140+
);
141+
}
142+
125143
$this->requestValidator->isValid($request);
126144
$this->bindingValidator->isValid($request);
127145

0 commit comments

Comments
 (0)