diff --git a/modules/multiauth/docs/multiauth.md b/modules/multiauth/docs/multiauth.md index 7b3e0f273740fe3dbe44cd07c642cee6d5a25cc0..97ae265feb2724b63d0c4b154b748d75cb6ca979 100644 --- a/modules/multiauth/docs/multiauth.md +++ b/modules/multiauth/docs/multiauth.md @@ -110,3 +110,27 @@ You can also use the multiauth:preselect parameter to the login call: $as->login(array( 'multiauth:preselect' => 'default-sp', )); + +Or add the `preselect` option in the filter: + + 'example-multi' => array( + 'multiauth:MultiAuth', + + /* + * The available authentication sources. + * They must be defined in this authsources.php file. + */ + 'sources' => array( + 'example-saml' => array( + // ... + ), + 'example-admin' => array( + // ... + ), + ), + 'preselect' => 'example-saml', + ), + +The order of priority, in case more than one option was used is: +`source` url parameter, `multiauth:preselect` login state and +`preselect` filter option. diff --git a/modules/multiauth/lib/Auth/Source/MultiAuth.php b/modules/multiauth/lib/Auth/Source/MultiAuth.php index abdf6064464af58700dd4220d55f1100e5a8b2c2..0ed57301892956fc1441e8d43bc2983a66db663f 100644 --- a/modules/multiauth/lib/Auth/Source/MultiAuth.php +++ b/modules/multiauth/lib/Auth/Source/MultiAuth.php @@ -37,6 +37,11 @@ class MultiAuth extends \SimpleSAML\Auth\Source */ private $sources; + /** + * @var string|null preselect source in filter module configuration + */ + private $preselect; + /** * Constructor for this authentication source. * @@ -55,6 +60,14 @@ class MultiAuth extends \SimpleSAML\Auth\Source throw new \Exception('The required "sources" config option was not found'); } + if (array_key_exists('preselect', $config) && is_string($config['preselect'])) { + if (!array_key_exists($config['preselect'], $config['sources'])) { + throw new \Exception('The optional "preselect" config option must be present in "sources"'); + } + + $this->preselect = $config['preselect']; + } + $globalConfiguration = \SimpleSAML\Configuration::getInstance(); $defaultLanguage = $globalConfiguration->getString('language.default', 'en'); $authsources = \SimpleSAML\Configuration::getConfig('authsources.php'); @@ -126,6 +139,10 @@ class MultiAuth extends \SimpleSAML\Auth\Source $url = \SimpleSAML\Module::getModuleURL('multiauth/selectsource.php'); $params = ['AuthState' => $id]; + if (!\array_key_exists('multiauth:preselect', $state) && is_string($this->preselect)) { + $state['multiauth:preselect'] = $this->preselect; + } + // Allowes the user to specify the auth souce to be used if (isset($_GET['source'])) { $params['source'] = $_GET['source']; diff --git a/tests/modules/multiauth/lib/Auth/Source/MultiAuthTest.php b/tests/modules/multiauth/lib/Auth/Source/MultiAuthTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d31543030378f04d3bc70242852680da0bd9bc3f --- /dev/null +++ b/tests/modules/multiauth/lib/Auth/Source/MultiAuthTest.php @@ -0,0 +1,203 @@ +<?php + +namespace SimpleSAML\Test\Module\multiauth\Auth\Source; + +use PHPUnit\Framework\TestCase; +use SimpleSAML\Configuration; +use SimpleSAML\Module\multiauth\Auth\Source\MultiAuth; + +class MultiAuthTest extends TestCase +{ + /** @var Configuration */ + private $sourceConfig; + + public function setUp() + { + $this->config = Configuration::loadFromArray(['module.enable' => ['multiauth' => true]], '[ARRAY]', 'simplesaml'); + Configuration::setPreLoadedConfig($this->config, 'config.php'); + + $this->sourceConfig = Configuration::loadFromArray(array( + 'example-multi' => array( + 'multiauth:MultiAuth', + + /* + * The available authentication sources. + * They must be defined in this authsources.php file. + */ + 'sources' => array( + 'example-saml' => array( + 'text' => array( + 'en' => 'Log in using a SAML SP', + 'es' => 'Entrar usando un SP SAML', + ), + 'css-class' => 'SAML', + ), + 'example-admin' => array( + 'text' => array( + 'en' => 'Log in using the admin password', + 'es' => 'Entrar usando la contraseña de administrador', + ), + ), + ), + 'preselect' => 'example-saml', + ), + + 'example-saml' => array( + 'saml:SP', + 'entityId' => 'my-entity-id', + 'idp' => 'my-idp', + ), + + 'example-admin' => array( + 'core:AdminPassword', + ), + )); + Configuration::setPreLoadedConfig($this->sourceConfig, 'authsources.php'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage The required "sources" config option was not found + */ + public function testSourcesMustBePresent() + { + $sourceConfig = Configuration::loadFromArray(array( + 'example-multi' => array( + 'multiauth:MultiAuth', + ), + )); + + Configuration::setPreLoadedConfig($sourceConfig, 'authsources.php'); + + new MultiAuth(['AuthId' => 'example-multi'], $sourceConfig->getArray('example-multi')); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage The optional "preselect" config option must be present in "sources" + */ + public function testPreselectMustBeValid() + { + $sourceConfig = Configuration::loadFromArray(array( + 'example-multi' => array( + 'multiauth:MultiAuth', + + /* + * The available authentication sources. + * They must be defined in this authsources.php file. + */ + 'sources' => array( + 'example-saml' => array( + 'text' => array( + 'en' => 'Log in using a SAML SP', + 'es' => 'Entrar usando un SP SAML', + ), + 'css-class' => 'SAML', + ), + 'example-admin' => array( + 'text' => array( + 'en' => 'Log in using the admin password', + 'es' => 'Entrar usando la contraseña de administrador', + ), + ), + ), + 'preselect' => 'other', + ), + + 'example-saml' => array( + 'saml:SP', + 'entityId' => 'my-entity-id', + 'idp' => 'my-idp', + ), + + 'example-admin' => array( + 'core:AdminPassword', + ), + )); + + Configuration::setPreLoadedConfig($sourceConfig, 'authsources.php'); + new MultiAuth(['AuthId' => 'example-multi'], $sourceConfig->getArray('example-multi')); + } + + public function testPreselectIsOptional() + { + $sourceConfig = Configuration::loadFromArray(array( + 'example-multi' => array( + 'multiauth:MultiAuth', + + /* + * The available authentication sources. + * They must be defined in this authsources.php file. + */ + 'sources' => array( + 'example-saml' => array( + 'text' => array( + 'en' => 'Log in using a SAML SP', + 'es' => 'Entrar usando un SP SAML', + ), + 'css-class' => 'SAML', + ), + 'example-admin' => array( + 'text' => array( + 'en' => 'Log in using the admin password', + 'es' => 'Entrar usando la contraseña de administrador', + ), + ), + ), + ), + + 'example-saml' => array( + 'saml:SP', + 'entityId' => 'my-entity-id', + 'idp' => 'my-idp', + ), + + 'example-admin' => array( + 'core:AdminPassword', + ), + )); + + Configuration::setPreLoadedConfig($sourceConfig, 'authsources.php'); + + $state = []; + $source = new MultiAuth(['AuthId' => 'example-multi'], $sourceConfig->getArray('example-multi')); + + try { + $source->authenticate($state); + } catch (\Error $e) { + } catch (\Exception $e) { + } + + $this->assertArrayNotHasKey('multiauth:preselect', $state); + } + + public function testPreselectCanBeConfigured() + { + $state = []; + + $source = new MultiAuth(['AuthId' => 'example-multi'], $this->sourceConfig->getArray('example-multi')); + + try { + $source->authenticate($state); + } catch (\Exception $e) { + } + + $this->assertArrayHasKey('multiauth:preselect', $state); + $this->assertEquals('example-saml', $state['multiauth:preselect']); + } + + public function testStatePreselectHasPriority() + { + $state = ['multiauth:preselect' => 'example-admin']; + + $source = new MultiAuth(['AuthId' => 'example-multi'], $this->sourceConfig->getArray('example-multi')); + + try { + $source->authenticate($state); + } catch (\Exception $e) { + } + + $this->assertArrayHasKey('multiauth:preselect', $state); + $this->assertEquals('example-admin', $state['multiauth:preselect']); + } +}