Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/packages/ci/parameters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ parameters:
api.users.nameidlookup.password: secret
feature_api_users_nameid_lookup: true
feature_hide_bookmarkable_url: true
wayf.remember_choice: false
feature_enable_wayf_remember_choice_per_idp: true
auth.log.attributes:
uid: 'urn:mace:dir:attribute-def:uid'
encryption_keys:
Expand Down
4 changes: 4 additions & 0 deletions src/OpenConext/EngineBlock/Metadata/EmptyMduiElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class EmptyMduiElement implements MultilingualElement, JsonSerializable
{
private $name;

public $height = null;
public $width = null;
public $url = null;

public function __construct(string $name)
{
$this->name = $name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use DOMDocument;
use DOMElement;
use DOMXPath;
use OpenConext\EngineBlock\Service\Wayf\RememberedIdpCookie;
use OpenConext\EngineBlockBundle\Sbs\Msg;
use OpenConext\EngineBlockFunctionalTestingBundle\Fixtures\DataStore\AbstractDataStore;
use OpenConext\EngineBlockFunctionalTestingBundle\Fixtures\FunctionalTestingAttributeAggregationClient;
Expand Down Expand Up @@ -392,6 +393,47 @@ public function iSelectOnTheWAYF($idpName)
$button->click();
}

/**
* @Given /^I select "([^"]*)" on the WAYF and remember my choice$/
*/
public function iSelectOnTheWAYFAndRememberMyChoice($idpName)
{
/** @var MockIdentityProvider $mockIdp */
$mockIdp = $this->mockIdpRegistry->get($idpName);

if (!$mockIdp) {
throw new RuntimeException(
sprintf('Unable to find idp with name "%s"', $idpName)
);
}

$page = $this->getMinkContext()->getSession()->getPage();
$selector = '[data-entityid="' . $mockIdp->entityId() . '"]';
$idpContainer = $page->find('css', $selector);

if (!$idpContainer) {
throw new RuntimeException(sprintf('Unable to find idp container with selector "%s"', $selector));
}

$rememberChoiceField = $idpContainer->find('css', 'input[name="rememberChoice"]');

if (!$rememberChoiceField) {
throw new RuntimeException(
sprintf('Unable to find hidden rememberChoice field within selector "%s"', $selector)
);
}

$rememberChoiceField->setValue('1');

$button = $idpContainer->find('css', 'button.idp__submit');

if (!$button) {
throw new RuntimeException(sprintf('Unable to find button with selector "%s button.idp__submit"', $selector));
}

$button->click();
}

/**
* @Given /^I select IdP by label "([^"]*)" on the WAYF$/
*/
Expand Down Expand Up @@ -510,6 +552,19 @@ public function iLoseMySession()
// set unknown session id to prevent session not found exception
$session->setCookie(session_name(), '000000');
}

/**
* @Given /^I start a new browser session$/
*/
public function iStartANewBrowserSession()
{
// Unlike I lose my session (which restarts the whole client and wipes every
// cookie), this only clears the PHP session cookie. This simulates a real
// browser starting a fresh PHP session (e.g. after the session naturally
// expires) while still sending along any other persistent cookies, such as
// the "rememberedidps" cookie, exactly as a real browser would.
$this->getMinkContext()->getSession()->setCookie(session_name(), null);
}
/**
* @Given /^I lose my session and reload$/
*/
Expand Down Expand Up @@ -726,6 +781,36 @@ public function aLangCookieShouldBeSetWithValue($locale)
}
}

/**
* @Then /^the "rememberedidps" cookie should be set$/
*/
public function theRememberedIdpsCookieShouldBeSet()
{
$cookie = $this->getMinkContext()->getSession()->getCookie(RememberedIdpCookie::NAME);

if ($cookie === null) {
throw new ExpectationException(
'The rememberedidps cookie has not been set',
$this->getMinkContext()->getSession()->getDriver()
);
}
}

/**
* @Then /^the "rememberedidps" cookie should not be set$/
*/
public function theRememberedIdpsCookieShouldNotBeSet()
{
$cookie = $this->getMinkContext()->getSession()->getCookie(RememberedIdpCookie::NAME);

if ($cookie !== null) {
throw new ExpectationException(
'The rememberedidps cookie should not be set, but it is',
$this->getMinkContext()->getSession()->getDriver()
);
}
}

/**
* @Given /^I have a locale cookie containing "([^"]*)"$/
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,19 @@ public function spIsConfiguredToDisplayOnlyConnectedIdps($spName)
->save();
}

/**
* @Given /^SP "([^"]*)" allows remembering the WAYF choice$/
* @param string $spName
*/
public function spAllowsRememberingTheWayfChoice($spName)
{
$sp = $this->anUnregisteredServiceProviderNamed($spName);

$this->serviceRegistryFixture
->allowWayfRememberChoiceForSp($sp->entityId())
->save();
}

/**
* @Given /^SP "([^"]*)" scopes its request to IDP "([^"]*)"$/
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
Feature:
In order to not have to pick my IdP every time I log in to the same SP
As a user
I want EngineBlock to remember my previous IdP choice for that SP

Background:
Given an EngineBlock instance on "dev.openconext.local"
And no registered SPs
And no registered Idps
And an Identity Provider named "Dummy-IdP"
And an Identity Provider named "Second-IdP"
And a Service Provider named "Remembering-SP"
And SP "Remembering-SP" allows remembering the WAYF choice
And a Service Provider named "Non-Remembering-SP"

Scenario: Remembering a choice skips the WAYF on a subsequent login

@johanib johanib Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without a existing session in EB.

I mean: This feature could be easily mistaken for the other 'remember my choice' & the test flows could be mistake if you do not clear your EB session cookie, which this new remember my choice feature is specifically for.

When I log in at "Remembering-SP"
And I select "Dummy-IdP" on the WAYF and remember my choice
And I pass through EngineBlock
And I pass through the IdP
Then the "rememberedidps" cookie should be set
When I give my consent
And I pass through EngineBlock
Then the url should match "functional-testing/Remembering-SP/acs"
And I start a new browser session
When I log in at "Remembering-SP"
And I pass through EngineBlock
Then the url should not match "authentication/proxy/wayf"
And the url should match "Dummy-IdP/sso"
When I pass through the IdP
When I pass through EngineBlock
Then the url should match "functional-testing/Remembering-SP/acs"

Scenario: The remembered choice is scoped per SP
Given a Service Provider named "Other-Remembering-SP"
And SP "Other-Remembering-SP" allows remembering the WAYF choice
When I log in at "Remembering-SP"
And I select "Dummy-IdP" on the WAYF and remember my choice
And I pass through EngineBlock
And I pass through the IdP
Then the "rememberedidps" cookie should be set
When I give my consent
And I pass through EngineBlock
Then the url should match "functional-testing/Remembering-SP/acs"
And I start a new browser session
When I log in at "Other-Remembering-SP"
And I select "Second-IdP" on the WAYF
And I pass through EngineBlock
And I pass through the IdP
When I give my consent
And I pass through EngineBlock
Then the url should match "functional-testing/Other-Remembering-SP/acs"

Scenario: An SP without the coin never gets the choice remembered
When I log in at "Non-Remembering-SP"
And I select "Dummy-IdP" on the WAYF and remember my choice
And I pass through EngineBlock
And I pass through the IdP
Then the "rememberedidps" cookie should not be set
When I give my consent
And I pass through EngineBlock
Then the url should match "functional-testing/Non-Remembering-SP/acs"
And I start a new browser session
When I log in at "Non-Remembering-SP"
And I select "Dummy-IdP" on the WAYF
And I pass through EngineBlock
And I pass through the IdP
When I give my consent
And I pass through EngineBlock
Then the url should match "functional-testing/Non-Remembering-SP/acs"

Scenario: The reset endpoint clears a remembered choice
When I log in at "Remembering-SP"
And I select "Dummy-IdP" on the WAYF and remember my choice
And I pass through EngineBlock
And I pass through the IdP
Then the "rememberedidps" cookie should be set
When I give my consent
And I pass through EngineBlock
Then the url should match "functional-testing/Remembering-SP/acs"
When I go to Engineblock URL "/reset-remember-wayf"
Then the "rememberedidps" cookie should not be set
And I start a new browser session
When I log in at "Remembering-SP"
And I select "Dummy-IdP" on the WAYF
And I pass through EngineBlock
And I pass through the IdP
When I give my consent
And I pass through EngineBlock
Then the url should match "functional-testing/Remembering-SP/acs"

Scenario: The cookie removal page lists and removes the remembered choice
When I log in at "Remembering-SP"
And I select "Dummy-IdP" on the WAYF and remember my choice
And I pass through EngineBlock
And I pass through the IdP
Then the "rememberedidps" cookie should be set
When I give my consent
And I pass through EngineBlock
Then the url should match "functional-testing/Remembering-SP/acs"
When I go to Engineblock URL "/authentication/idp/remove-cookies"
Then the response should contain 'rememberedidps'
When I press "remove_rememberedidps"
Then the "rememberedidps" cookie should not be set
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,13 @@ public function displayUnconnectedIdpsForSp($entityId, $displayUnconnected = tru
return $this;
}

public function allowWayfRememberChoiceForSp($entityId)
{
$this->setCoin($this->getServiceProvider($entityId), 'wayfRememberChoice', true);

return $this;
}

public function disconnectSp($spEntityId, $idpEntityId)
{
$sp = $this->getServiceProvider($spEntityId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* This doesn't run in CI, which is why it's skipped. You can run it locally by setting the wayf.remember_choice flag to true in parameters.yaml.
* This doesn't run in CI, which is why it's skipped. You can run it locally by setting either the wayf.remember_choice flag or the feature_enable_wayf_remember_choice_per_idp flag to true in parameters.yaml.
*/
context.skip('Cookie removal page verify a11y', () => {
beforeEach(() => {
Expand Down
Loading
Loading