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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ More information about our release strategy can be found in
the [Development Guidelines](https://github.com/OpenConext/OpenConext-engineblock/wiki/Development-Guidelines#release-notes)
on the EngineBlock wiki.

## UNRELEASED
Features:
* Added `eb.stepup.send_service_name` feature flag. When enabled, EngineBlock adds an `mdui:UIInfo`/`DisplayName` extension with the SP's display name to the Stepup callout AuthnRequest (#2034).

## 7.2.0

Maintenance:
Expand Down
1 change: 1 addition & 0 deletions config/packages/engineblock_features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ parameters:
eb.feature_enable_idp_initiated_flow: "%feature_enable_idp_initiated_flow%"
eb.stepup.sfo.override_engine_entityid: "%feature_stepup_sfo_override_engine_entityid%"
eb.stepup.send_user_attributes: "%feature_stepup_send_user_attributes%"
eb.stepup.send_service_name: "%feature_stepup_send_service_name%"
eb.feature_enable_sram_interrupt: "%feature_enable_sram_interrupt%"
eb.hide_bookmarkable_url: "%feature_hide_bookmarkable_url%"
1 change: 1 addition & 0 deletions config/packages/parameters.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ parameters:
feature_enable_idp_initiated_flow: true
feature_stepup_sfo_override_engine_entityid: false
feature_stepup_send_user_attributes: false
feature_stepup_send_service_name: false
Comment thread
johanib marked this conversation as resolved.
feature_enable_sram_interrupt: false
feature_hide_bookmarkable_url: false

Expand Down
18 changes: 17 additions & 1 deletion library/EngineBlock/Corto/ProxyServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use OpenConext\EngineBlock\Metadata\Service;
use OpenConext\EngineBlock\Metadata\TransparentMfaEntity;
use OpenConext\EngineBlock\Stepup\StepupGsspUserAttributeExtension;
use OpenConext\EngineBlock\Stepup\StepupServiceNameExtension;
use OpenConext\EngineBlock\Metadata\X509\KeyPairFactory;
use OpenConext\EngineBlockBundle\Authentication\AuthenticationState;
use OpenConext\EngineBlockBundle\Exception\UnknownKeyIdException;
Expand Down Expand Up @@ -486,7 +487,8 @@ public function sendStepupAuthenticationRequest(
Loa $authnContextClassRef,
NameID $nameId,
bool $isForceAuthn,
Assertion $originalAssertion
Assertion $originalAssertion,
?ServiceProvider $sp = null,
Comment thread
johanib marked this conversation as resolved.
): void {
$ebRequest = EngineBlock_Saml2_AuthnRequestFactory::createFromRequest(
$spRequest,
Expand Down Expand Up @@ -555,6 +557,19 @@ public function sendStepupAuthenticationRequest(
}
}

$isSendServiceNameConfigured = $features->hasFeature('eb.stepup.send_service_name');
Comment thread
johanib marked this conversation as resolved.
$isSendServiceNameEnabled = $features->isEnabled('eb.stepup.send_service_name');

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.

move to inline if, so it doesnt get called if feature flag is not set


if ($isSendServiceNameConfigured && $isSendServiceNameEnabled && $sp !== null) {
$localeProvider = $container->getLocaleProvider();
StepupServiceNameExtension::add(
$sspMessage,
$sp,
$localeProvider->getLocale(),
$localeProvider->getDefaultLocale(),
$localeProvider->getAvailableLocales(),
);
}

// Link with the original Request
$diContainerRuntime = EngineBlock_ApplicationSingleton::getInstance()->getDiContainerRuntime();
Expand Down Expand Up @@ -635,6 +650,7 @@ public function handleStepupAuthenticationCallout(
$nameId,
$sp->getCoins()->isStepupForceAuthn(),
$originalAssertion,
$sp,
);
}

Expand Down
90 changes: 90 additions & 0 deletions src/OpenConext/EngineBlock/Stepup/StepupServiceNameExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

/**
* Copyright 2026 SURFnet B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace OpenConext\EngineBlock\Stepup;

use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider;
use SAML2\DOMDocumentFactory;
use SAML2\Message;
use SAML2\XML\Chunk;

final class StepupServiceNameExtension
{
private const MDUI_NS = 'urn:oasis:names:tc:SAML:metadata:ui';

/**
* @param string[] $availableLocales
*/
public static function add(
Message $message,
ServiceProvider $sp,
string $locale,
string $defaultLocale,
array $availableLocales,
): void {
if (!in_array($locale, $availableLocales, true)) {
$locale = $defaultLocale;
}
$result = self::resolveName($sp, $locale);
if ($result === null && $locale !== $defaultLocale) {
$result = self::resolveName($sp, $defaultLocale);
}
if ($result === null) {
return;
}
[$resolvedLocale, $name] = $result;

$dom = DOMDocumentFactory::create();
$uiInfo = $dom->createElementNS(self::MDUI_NS, 'mdui:UIInfo');
$displayName = $dom->createElementNS(self::MDUI_NS, 'mdui:DisplayName');
$displayName->setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:lang', $resolvedLocale);
$displayName->textContent = $name;
$uiInfo->appendChild($displayName);

$ext = $message->getExtensions();
$ext['mdui:UIInfo'] = new Chunk($uiInfo);
Comment thread
johanib marked this conversation as resolved.
$message->setExtensions($ext);
}

/**
* @return array{string, string}|null
*/
private static function resolveName(ServiceProvider $sp, string $locale): ?array
Comment thread
johanib marked this conversation as resolved.
{
$name = $sp->getMdui()->getDisplayNameOrNull($locale);
if (empty($name)) {
$name = self::localizedName($sp, $locale);
}
if (empty($name)) {
return null;
}
return [$locale, $name];
}

private static function localizedName(ServiceProvider $sp, string $locale): ?string
{
return match ($locale) {
'en' => $sp->nameEn,
'nl' => $sp->nameNl,
'pt' => $sp->namePt,
default => null,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function __construct()
$this->setFeature(new Feature('eb.stepup.sfo.override_engine_entityid', false));
$this->setFeature(new Feature('eb.feature_enable_idp_initiated_flow', true));
$this->setFeature(new Feature('eb.stepup.send_user_attributes', true));
$this->setFeature(new Feature('eb.stepup.send_service_name', false));
$this->setFeature(new Feature('eb.feature_enable_sram_interrupt', true));
$this->setFeature(new Feature('eb.hide_bookmarkable_url', true));
}
Expand Down
16 changes: 16 additions & 0 deletions src/OpenConext/EngineBlockBundle/Localization/LocaleProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ public function scopeWithRequest(Request $request)
$this->request = $request;
}

/**
* @return string
*/
public function getDefaultLocale()
{
return $this->defaultLocale;
}

/**
* @return string[]
*/
public function getAvailableLocales()
{
return $this->availableLocales;
}

/**
* @return string
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ public function theAuthnRequestToSubmitShouldMatchXpath($xpath)

$xpathObject = new DOMXPath($authnRequest);
$xpathObject->registerNamespace('gssp', 'urn:mace:surf.nl:stepup:gssp-extensions');
$xpathObject->registerNamespace('mdui', 'urn:oasis:names:tc:SAML:metadata:ui');
$nodeList = $xpathObject->query($xpath);

if (!$nodeList || $nodeList->length === 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,20 @@ Feature:
And I pass through EngineBlock
And I pass through the IdP
Then the received AuthnRequest should match xpath '/samlp:AuthnRequest/samlp:Extensions/gssp:UserAttributes/saml:Attribute[@Name="urn:mace:dir:attribute-def:mail"]/saml:AttributeValue[text()="j.doe@institution-a.example.org"]'

Scenario: Stepup callout includes service name in mdui:UIInfo when feature is enabled
Given the SP "SSO-SP" requires Stepup LoA "http://dev.openconext.local/assurance/loa2"
And feature "eb.stepup.send_service_name" is enabled
When I log in at "SSO-SP"
And I select "SSO-IdP" on the WAYF
And I pass through EngineBlock
And I pass through the IdP
Then the received AuthnRequest should match xpath '/samlp:AuthnRequest/samlp:Extensions/mdui:UIInfo/mdui:DisplayName'

Scenario: Stepup callout does not include service name in mdui:UIInfo when feature is disabled
Given the SP "SSO-SP" requires Stepup LoA "http://dev.openconext.local/assurance/loa2"
When I log in at "SSO-SP"
And I select "SSO-IdP" on the WAYF
And I pass through EngineBlock
And I pass through the IdP
Then the received AuthnRequest should not match xpath '/samlp:AuthnRequest/samlp:Extensions/mdui:UIInfo/mdui:DisplayName'
Loading