diff --git a/composer.json b/composer.json index 3cd2f7c03c622cbf10d68db98bc3113a034db688..9ac179e37dbd75f34c6b0904d33ad85ca39eeeb6 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,7 @@ "ext-mbstring": "*", "gettext/gettext": "^4.6", "phpmailer/phpmailer": "^6.1", - "simplesamlphp/assert": "^0.2.6", + "simplesamlphp/assert": "^0.2.7", "simplesamlphp/saml2": "^4.2.3", "simplesamlphp/twig-configurable-i18n": "^2.3", "symfony/cache": "^4.0 || ^5.0", diff --git a/composer.lock b/composer.lock index aeaa4a41df7f7ab558ea43cf522624660e497e28..da5665c1237914022f8aed2a55b939f93c92fd79 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3f7b1c658a21ed99cf2359c5ac11761f", + "content-hash": "3454198cab8a477aa3697b77ec51f1a9", "packages": [ { "name": "gettext/gettext", @@ -469,22 +469,22 @@ }, { "name": "simplesamlphp/assert", - "version": "v0.2.6", + "version": "v0.2.7", "source": { "type": "git", "url": "https://github.com/simplesamlphp/assert.git", - "reference": "fbbf5df9f7d25c2049ad4681d64262abec095c40" + "reference": "d1d568ac85c133b7ec517cb00e7eda7f6a40e063" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/assert/zipball/fbbf5df9f7d25c2049ad4681d64262abec095c40", - "reference": "fbbf5df9f7d25c2049ad4681d64262abec095c40", + "url": "https://api.github.com/repos/simplesamlphp/assert/zipball/d1d568ac85c133b7ec517cb00e7eda7f6a40e063", + "reference": "d1d568ac85c133b7ec517cb00e7eda7f6a40e063", "shasum": "" }, "require": { "ext-spl": "*", "php": "^7.4 || ^8.0", - "webmozart/assert": "^1.9" + "webmozart/assert": "^1.10" }, "require-dev": { "simplesamlphp/simplesamlphp-test-framework": "^1.0.5" @@ -517,9 +517,9 @@ "description": "A wrapper around webmozart/assert to make it useful beyond checking method arguments", "support": { "issues": "https://github.com/simplesamlphp/assert/issues", - "source": "https://github.com/simplesamlphp/assert/tree/v0.2.6" + "source": "https://github.com/simplesamlphp/assert/tree/v0.2.7" }, - "time": "2021-04-07T17:19:30+00:00" + "time": "2021-07-24T19:23:31+00:00" }, { "name": "simplesamlphp/saml2", @@ -6482,5 +6482,5 @@ "platform-dev": { "ext-curl": "*" }, - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.1.0" } diff --git a/docs/simplesamlphp-theming.md b/docs/simplesamlphp-theming.md index 7cc62a777b6aa7254fdd6a127a599a266dfd7162..e9b8c09eb2aca3f290fc045cf6121af3cb917592 100644 --- a/docs/simplesamlphp-theming.md +++ b/docs/simplesamlphp-theming.md @@ -22,19 +22,23 @@ If you want to customize the UI, the right way to do that is to create a new **t ### Configuring which theme to use -In `config.php` there is a configuration option that controls theming. Here is an example: +In `config.php` there is a configuration option that controls theming. You need to set that option and enable the module that contains the theme. Here is an example: - 'theme.use' => 'fancymodule:fancytheme', + 'module.enable' => [ + ... + 'fancymodule' => true, + ], -The `theme.use` parameter points to which theme that will be used. If some functionality in SimpleSAMLphp needs to present UI in example with the `logout.php` template, it will first look for `logout.php` in the `theme.use` theme, and if not found it will all fallback to look for the base templates. + 'theme.use' => 'fancymodule:fancytheme', -All required templates SHOULD be available as a base in the `templates` folder, and you SHOULD never change the base templates. To customize UI, add a new theme within a module that overrides the base templates, instead of modifying it. +The `theme.use` parameter points to which theme that will be used. If some functionality in SimpleSAMLphp needs to present UI in example with the `logout.twig` template, it will first look for `logout.twig` in the `theme.use` theme, and if not found it will all fallback to look for the base templates. -### Templates that include other files +All required templates SHOULD be available as a base in the `templates` folder, and you SHOULD never change the base templates. To customize UI, add a new theme within a module that overrides the base templates, instead of modifying it. -A template file may *include* other files. For example all the default templates will include a header and footer: the `login.php` template will first include `includes/header.php` then present the login page, and then include `includes/footer.php`. +### Override only specific templates -SimpleSAMLphp allows themes to override the included templates files only, if needed. That means you can create a new theme `fancytheme` that includes only a header and footer. The header file refers to the CSS files, which means that a simple way of making a new look on SimpleSAMLphp is to create a new theme, and copy the existing header, but point to your own CSS instead of the default CSS. +The SimpleSAMLphp templates are derived from a base template and include other templates as building blocks. You only need to override the templates or building blocks needed for your change. +SimpleSAMLphp allows themes to override the included templates files only, if needed. That means you can create a new theme `fancytheme` that includes only a header and footer template. These templates may refer to your own CSS files, which means that a simple way of making a new look on SimpleSAMLphp is to create a new theme, and copy the existing header, but point to your own CSS instead of the default CSS. Creating your first theme @@ -50,51 +54,22 @@ The first thing you need to do is having a SimpleSAMLphp module to place your th Then within this module, you can create a new theme named `fancytheme`. cd modules/mymodule - mkdir -p themes/fancytheme/default/includes + mkdir -p themes/fancytheme/default/ Now, configure SimpleSAMLphp to use your new theme in `config.php`: 'theme.use' => 'mymodule:fancytheme', -Next, we create `themes/fancytheme/default/includes`, and copy the header file from the base theme: - - cp templates/includes/header.php modules/mymodule/themes/fancytheme/default/includes/ - -In the `modules/mymodule/themes/fancytheme/default/includes/header.php` type in something and go to the SimpleSAMLphp front page to see that your new theme is in use. - -A good start is to modify the reference to the default CSS: - - <link rel="stylesheet" type="text/css" href="/<?php echo $this->data['baseurlpath']; ?>resources/default.css" /> - -to in example: - - <link rel="stylesheet" type="text/css" href="/<?php echo $this->data['baseurlpath']; ?>resources/fancytheme/default.css" /> - - -Examples ---------------------- - -To override the frontpage body, add the file: - - modules/mymodule/themes/fancytheme/default/frontpage.php - -In the path above `default` means that the frontpage template is not part of any modules. If you are replacing a template that is part of a module, then use the module name instead of `default`. - -For example, to override the `preprodwarning` template, (the file is located in `modules/preprodwarning/templates/warning.php`), you need to add a new file: - - modules/mymodule/themes/fancytheme/preprodwarning/warning.php - +Next, we copy the header file from the base theme: -Say in a module `foomodule`, some code requests to present the `bar.php` template, SimpleSAMLphp will: - - 1. first look in your theme for a replacement: `modules/mymodule/themes/fancytheme/foomodule/bar.php`. - 2. If not found, it will use the base template of that module: `modules/foomodule/templates/bar.php` + cp templates/_header.twig modules/mymodule/themes/fancytheme/default/ +In the `modules/mymodule/themes/fancytheme/default/includes/_header.twig` file type in something and go to the SimpleSAMLphp front page to see that your new theme is in use. Adding resource files --------------------- -You can put resource files within the www folder of your module, to make your module completely independent with included css, icons etc. +You can put resource files within the `www/assets` folder of your module, to make your module completely independent with included css, icons etc. ``` modules @@ -102,18 +77,17 @@ modules └───lib └───themes └───www - └───logo.png - └───style.css -``` - -Reference these resources in your custom PHP templates under `themes/fancytheme` by using a generator for the URL: -``` -<?php echo SimpleSAML\Module::getModuleURL('mymodule/logo.png'); ?> + └───assets + └───logo.png + └───style.css ``` +Reference these resources in your custom templates under `themes/fancytheme` by using a generator for the URL. Example for a custom CSS stylesheet file: ``` -<link rel="stylesheet" href="<?php echo SimpleSAML\Module::getModuleURL('mymodule/style.css'); ?>"> +{% block preload %} +<link rel="stylesheet" href="{{ asset('style.css', 'mymodule') }}"> +{% endblock %} ``` Migrating to Twig templates @@ -129,7 +103,7 @@ If you need to make more extensive customizations to the base template, you shou cp templates/base.twig modules/mymodule/themes/fancytheme/default/ -Any references to `$this->data['baseurlpath']` in old-style templates can be replaced with `{{baseurlpath}}` in Twig templates. Likewise, references to `\SimpleSAML\Module::getModuleURL()` can be replaced with `{{baseurlpath}}module.php/mymodule/...` +Any references to `$this->data['baseurlpath']` in old-style templates can be replaced with `{{baseurlpath}}` in Twig templates. Likewise, references to `\SimpleSAML\Module::getModuleURL()` can be replaced with `{{baseurlpath}}module.php/mymodule/...` or the `asset()` function like shown above. Within templates each module is defined as a separate namespace matching the module name. This allows one template to reference templates from other modules using Twig's `@namespace_name/template_path` notation. For instance, a template in `mymodule` can include the widget template from the `yourmodule` module using the notation `@yourmodule/widget.twig`. A special namespace, `__parent__`, exists to allow theme developers to more easily extend a module's stock template. diff --git a/lib/SimpleSAML/Auth/ProcessingFilter.php b/lib/SimpleSAML/Auth/ProcessingFilter.php index a83c348b158ac04d9ac35252bcc0ce0f6f30bf2d..65827c6dfd5491c9749534eba5a81871fe17e667 100644 --- a/lib/SimpleSAML/Auth/ProcessingFilter.php +++ b/lib/SimpleSAML/Auth/ProcessingFilter.php @@ -60,7 +60,7 @@ abstract class ProcessingFilter * * When a filter returns from this function, it is assumed to have completed its task. * - * @param array &$request The request we are currently processing. + * @param array &$state The request we are currently processing. */ - abstract public function process(array &$request): void; + abstract public function process(array &$state): void; } diff --git a/lib/SimpleSAML/Error/CriticalConfigurationError.php b/lib/SimpleSAML/Error/CriticalConfigurationError.php index 9add0d009dc3007efb1dcdfb20243b18e478cd8e..04b2a044862f45afaaa20efbcbc6135ac3995b2a 100644 --- a/lib/SimpleSAML/Error/CriticalConfigurationError.php +++ b/lib/SimpleSAML/Error/CriticalConfigurationError.php @@ -67,19 +67,19 @@ class CriticalConfigurationError extends ConfigurationError /** - * @param \Throwable $exception + * @param \Throwable $e * * @return \SimpleSAML\Error\CriticalConfigurationError */ - public static function fromException(Throwable $exception): CriticalConfigurationError + public static function fromException(Throwable $e): CriticalConfigurationError { $reason = null; $file = null; - if ($exception instanceof ConfigurationError) { - $reason = $exception->getReason(); - $file = $exception->getConfFile(); + if ($e instanceof ConfigurationError) { + $reason = $e->getReason(); + $file = $e->getConfFile(); } else { - $reason = $exception->getMessage(); + $reason = $e->getMessage(); } return new CriticalConfigurationError($reason, $file); } diff --git a/lib/SimpleSAML/Locale/Localization.php b/lib/SimpleSAML/Locale/Localization.php index 21c606062789dee2388e4e08e4d86b1196d2eb53..ae621c2cfb64ac1d8afaa11068da96bba292d271 100644 --- a/lib/SimpleSAML/Locale/Localization.php +++ b/lib/SimpleSAML/Locale/Localization.php @@ -206,7 +206,7 @@ class Localization } // Locale for default language missing even, error out - $error = "Localization directory missing/broken for langcode '$langcode' and domain '$domain'"; + $error = "Localization directory '$langPath' missing/broken for langcode '$langcode' and domain '$domain'"; Logger::critical($_SERVER['PHP_SELF'] . ' - ' . $error); throw new \Exception($error); } diff --git a/lib/SimpleSAML/Locale/Translate.php b/lib/SimpleSAML/Locale/Translate.php index 9285aaf90eb81dbf7efc6dde406d9c75a9a1d436..4c26b670da39dd9cf51e955c089fb02765b85c56 100644 --- a/lib/SimpleSAML/Locale/Translate.php +++ b/lib/SimpleSAML/Locale/Translate.php @@ -143,45 +143,6 @@ class Translate } - /** - * Retrieve the preferred translation of a given text. - * - * @param array $translations The translations, as an associative array with language => text mappings. - * - * @return string The preferred translation. - * - * @throws \Exception If there's no suitable translation. - */ - public function getPreferredTranslation(array $translations): string - { - // look up translation of tag in the selected language - $selected_language = $this->language->getLanguage(); - if (array_key_exists($selected_language, $translations)) { - return $translations[$selected_language]; - } - - // look up translation of tag in the default language - $default_language = $this->language->getDefaultLanguage(); - if (array_key_exists($default_language, $translations)) { - return $translations[$default_language]; - } - - // check for english translation - if (array_key_exists('en', $translations)) { - return $translations['en']; - } - - // pick the first translation available - if (count($translations) > 0) { - $languages = array_keys($translations); - return $translations[$languages[0]]; - } - - // we don't have anything to return - throw new \Exception('Nothing to return from translation.'); - } - - /** * Translate the name of an attribute. * diff --git a/lib/SimpleSAML/XHTML/Template.php b/lib/SimpleSAML/XHTML/Template.php index e75907e636441bab1a95e2a77ea1b2c682877350..f9df3c72cda1e154ec698ec6afb8b96507b8fbcf 100644 --- a/lib/SimpleSAML/XHTML/Template.php +++ b/lib/SimpleSAML/XHTML/Template.php @@ -351,11 +351,9 @@ class Template extends Response // setup directories & namespaces $themeDir = Module::getModuleDir($this->theme['module']) . '/themes/' . $this->theme['name']; - $subdirs = scandir($themeDir); + $subdirs = @scandir($themeDir); if (empty($subdirs)) { - // no subdirectories in the theme directory, nothing to do here - // this is probably wrong, log a message - Logger::warning('Empty theme directory for theme "' . $this->theme['name'] . '".'); + Logger::warning('Theme directory for theme "' . $this->theme['name'] . '" (' . $themeDir . ') is not readable or is empty.'); return []; } diff --git a/modules/admin/lib/Controller/Test.php b/modules/admin/lib/Controller/Test.php index b93e80e6b50a7f703af020a977db63bd3fa90c90..383debf0a8a696d65b274f7c5bddb5eabbfeedcc 100644 --- a/modules/admin/lib/Controller/Test.php +++ b/modules/admin/lib/Controller/Test.php @@ -180,10 +180,7 @@ class Test "NameId" => [$nameId->getValue()], ]; if ($nameId->getFormat() !== null) { - $format = $translator->getPreferredTranslation( - $translator->getTag('{status:subject_format}') ?? ['en' => 'Format'] - ); - $list[$format] = [$nameId->getFormat()]; + $list['Format'] = [$nameId->getFormat()]; } if ($nameId->getNameQualifier() !== null) { $list['NameQualifier'] = [$nameId->getNameQualifier()]; @@ -327,10 +324,7 @@ class Test 'NameID' => [$nameID->getValue()], ]; if ($nameID->getFormat() !== null) { - $format = $t->getPreferredTranslation( - $t->getTag('{status:subject_format}') ?? ['en' => 'Format'] - ); - $eptid[$format] = [$nameID->getFormat()]; + $eptid['Format'] = [$nameID->getFormat()]; } if ($nameID->getNameQualifier() !== null) { $eptid['NameQualifier'] = [$nameID->getNameQualifier()]; diff --git a/modules/core/lib/Auth/Process/AttributeAdd.php b/modules/core/lib/Auth/Process/AttributeAdd.php index d30084a8738a59201f39f8c7e14d9d92b0ccab9a..10c571fb5b761c0771372454a9daa5167e8e575b 100644 --- a/modules/core/lib/Auth/Process/AttributeAdd.php +++ b/modules/core/lib/Auth/Process/AttributeAdd.php @@ -73,13 +73,13 @@ class AttributeAdd extends Auth\ProcessingFilter * * Add or replace existing attributes with the configured values. * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); - $attributes = &$request['Attributes']; + $attributes = &$state['Attributes']; foreach ($this->attributes as $name => $values) { if ($this->replace === true || !array_key_exists($name, $attributes)) { diff --git a/modules/core/lib/Auth/Process/AttributeAlter.php b/modules/core/lib/Auth/Process/AttributeAlter.php index 29a2c0823aa7aae0041d2c46217cf20168875147..e6db082d689f69639292666a4b0e367c33b7fc6e 100644 --- a/modules/core/lib/Auth/Process/AttributeAlter.php +++ b/modules/core/lib/Auth/Process/AttributeAlter.php @@ -99,15 +99,15 @@ class AttributeAlter extends Auth\ProcessingFilter * * Modify existing attributes with the configured values. * - * @param array &$request The current request. + * @param array &$state The current request. * @throws \SimpleSAML\Error\Exception In case of invalid configuration. */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); // get attributes from request - $attributes = &$request['Attributes']; + $attributes = &$state['Attributes']; // check that all required params are set in config if (empty($this->pattern) || empty($this->subject)) { diff --git a/modules/core/lib/Auth/Process/AttributeCopy.php b/modules/core/lib/Auth/Process/AttributeCopy.php index 199e4a8a24464f419878d27891bd638f4544a0eb..31c9297675b925ccb884f6d85c17d4a238320cd1 100644 --- a/modules/core/lib/Auth/Process/AttributeCopy.php +++ b/modules/core/lib/Auth/Process/AttributeCopy.php @@ -58,13 +58,13 @@ class AttributeCopy extends Auth\ProcessingFilter /** * Apply filter to rename attributes. * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); - $attributes = &$request['Attributes']; + $attributes = &$state['Attributes']; foreach ($attributes as $name => $values) { if (array_key_exists($name, $this->map)) { diff --git a/modules/core/lib/Auth/Process/AttributeLimit.php b/modules/core/lib/Auth/Process/AttributeLimit.php index 490940f3084293df10e530658373634bac353679..e2f3c5041ae4c1b6f1c9248d19e1963d6af75db9 100644 --- a/modules/core/lib/Auth/Process/AttributeLimit.php +++ b/modules/core/lib/Auth/Process/AttributeLimit.php @@ -64,18 +64,18 @@ class AttributeLimit extends Auth\ProcessingFilter /** * Get list of allowed from the SP/IdP config. * - * @param array &$request The current request. + * @param array &$state The current request. * @return array|null Array with attribute names, or NULL if no limit is placed. */ - private static function getSPIdPAllowed(array &$request): ?array + private static function getSPIdPAllowed(array &$state): ?array { - if (array_key_exists('attributes', $request['Destination'])) { + if (array_key_exists('attributes', $state['Destination'])) { // SP Config - return $request['Destination']['attributes']; + return $state['Destination']['attributes']; } - if (array_key_exists('attributes', $request['Source'])) { + if (array_key_exists('attributes', $state['Source'])) { // IdP Config - return $request['Source']['attributes']; + return $state['Source']['attributes']; } return null; } @@ -86,29 +86,29 @@ class AttributeLimit extends Auth\ProcessingFilter * * Removes all attributes which aren't one of the allowed attributes. * - * @param array &$request The current request + * @param array &$state The current request * @throws \SimpleSAML\Error\Exception If invalid configuration is found. */ - public function process(array &$request): void + public function process(array &$state): void { - assert::keyExists($request, 'Attributes'); + assert::keyExists($state, 'Attributes'); if ($this->isDefault) { - $allowedAttributes = self::getSPIdPAllowed($request); + $allowedAttributes = self::getSPIdPAllowed($state); if ($allowedAttributes === null) { $allowedAttributes = $this->allowedAttributes; } } elseif (!empty($this->allowedAttributes)) { $allowedAttributes = $this->allowedAttributes; } else { - $allowedAttributes = self::getSPIdPAllowed($request); + $allowedAttributes = self::getSPIdPAllowed($state); if ($allowedAttributes === null) { // No limit on attributes return; } } - $attributes = &$request['Attributes']; + $attributes = &$state['Attributes']; foreach ($attributes as $name => $values) { if (!in_array($name, $allowedAttributes, true)) { diff --git a/modules/core/lib/Auth/Process/AttributeMap.php b/modules/core/lib/Auth/Process/AttributeMap.php index 3fd36bdae63c4c997d8df4d17133569052e6bccc..16cf735ddbc1285e98f175df17d298ea75079ba1 100644 --- a/modules/core/lib/Auth/Process/AttributeMap.php +++ b/modules/core/lib/Auth/Process/AttributeMap.php @@ -115,15 +115,15 @@ class AttributeMap extends Auth\ProcessingFilter /** * Apply filter to rename attributes. * - * @param array &$request The current request. + * @param array &$state The current request. */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); $mapped_attributes = []; - foreach ($request['Attributes'] as $name => $values) { + foreach ($state['Attributes'] as $name => $values) { if (array_key_exists($name, $this->map)) { if (!is_array($this->map[$name])) { if ($this->duplicate) { @@ -146,6 +146,6 @@ class AttributeMap extends Auth\ProcessingFilter } } - $request['Attributes'] = $mapped_attributes; + $state['Attributes'] = $mapped_attributes; } } diff --git a/modules/core/lib/Auth/Process/AttributeValueMap.php b/modules/core/lib/Auth/Process/AttributeValueMap.php index 26636d35bb4d020a40d1c76d9bc0a77e912370dd..e4457633b0fe16ece896f4762069c42add634cc5 100644 --- a/modules/core/lib/Auth/Process/AttributeValueMap.php +++ b/modules/core/lib/Auth/Process/AttributeValueMap.php @@ -107,14 +107,14 @@ class AttributeValueMap extends Auth\ProcessingFilter /** * Apply filter. * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { Logger::debug('Processing the AttributeValueMap filter.'); - Assert::keyExists($request, 'Attributes'); - $attributes = &$request['Attributes']; + Assert::keyExists($state, 'Attributes'); + $attributes = &$state['Attributes']; if (!array_key_exists($this->sourceattribute, $attributes)) { // the source attribute does not exist, nothing to do here diff --git a/modules/core/lib/Auth/Process/Cardinality.php b/modules/core/lib/Auth/Process/Cardinality.php index 0a15500e0084f7419f8dbfa3d6c48b3ad13865f7..bbc3e4603564dc3a872dccf5fa410270c986d6b4 100644 --- a/modules/core/lib/Auth/Process/Cardinality.php +++ b/modules/core/lib/Auth/Process/Cardinality.php @@ -106,22 +106,22 @@ class Cardinality extends Auth\ProcessingFilter /** * Process this filter * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); $entityid = false; - if (array_key_exists('Source', $request) && array_key_exists('entityid', $request['Source'])) { - $entityid = $request['Source']['entityid']; + if (array_key_exists('Source', $state) && array_key_exists('entityid', $state['Source'])) { + $entityid = $state['Source']['entityid']; } if (in_array($entityid, $this->ignoreEntities, true)) { Logger::debug('Cardinality: Ignoring assertions from ' . $entityid); return; } - foreach ($request['Attributes'] as $k => $v) { + foreach ($state['Attributes'] as $k => $v) { if (!array_key_exists($k, $this->cardinality)) { continue; } @@ -142,7 +142,7 @@ class Cardinality extends Auth\ProcessingFilter ) ); } else { - $request['core:cardinality:errorAttributes'][$k] = [ + $state['core:cardinality:errorAttributes'][$k] = [ count($v), $this->cardinality[$k]['_expr'] ]; @@ -163,7 +163,7 @@ class Cardinality extends Auth\ProcessingFilter ) ); } else { - $request['core:cardinality:errorAttributes'][$k] = [ + $state['core:cardinality:errorAttributes'][$k] = [ count($v), $this->cardinality[$k]['_expr'] ]; @@ -174,7 +174,7 @@ class Cardinality extends Auth\ProcessingFilter /* check for missing attributes with a minimum cardinality */ foreach ($this->cardinality as $k => $v) { - if (!$this->cardinality[$k]['min'] || array_key_exists($k, $request['Attributes'])) { + if (!$this->cardinality[$k]['min'] || array_key_exists($k, $state['Attributes'])) { continue; } if ($this->cardinality[$k]['warn']) { @@ -184,7 +184,7 @@ class Cardinality extends Auth\ProcessingFilter $entityid )); } else { - $request['core:cardinality:errorAttributes'][$k] = [ + $state['core:cardinality:errorAttributes'][$k] = [ 0, $this->cardinality[$k]['_expr'] ]; @@ -192,8 +192,8 @@ class Cardinality extends Auth\ProcessingFilter } /* abort if we found a problematic attribute */ - if (array_key_exists('core:cardinality:errorAttributes', $request)) { - $id = Auth\State::saveState($request, 'core:cardinality'); + if (array_key_exists('core:cardinality:errorAttributes', $state)) { + $id = Auth\State::saveState($state, 'core:cardinality'); $url = Module::getModuleURL('core/cardinality_error.php'); $this->httpUtils->redirectTrustedURL($url, ['StateId' => $id]); return; diff --git a/modules/core/lib/Auth/Process/CardinalitySingle.php b/modules/core/lib/Auth/Process/CardinalitySingle.php index 64c5e059583bd511c62c4a292e66c1da79db3ebf..4b31a2b456c8663be5ca566011a86b6aad92100a 100644 --- a/modules/core/lib/Auth/Process/CardinalitySingle.php +++ b/modules/core/lib/Auth/Process/CardinalitySingle.php @@ -81,22 +81,22 @@ class CardinalitySingle extends Auth\ProcessingFilter /** * Process this filter * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); if ( - array_key_exists('Source', $request) - && array_key_exists('entityid', $request['Source']) - && in_array($request['Source']['entityid'], $this->ignoreEntities, true) + array_key_exists('Source', $state) + && array_key_exists('entityid', $state['Source']) + && in_array($state['Source']['entityid'], $this->ignoreEntities, true) ) { - Logger::debug('CardinalitySingle: Ignoring assertions from ' . $request['Source']['entityid']); + Logger::debug('CardinalitySingle: Ignoring assertions from ' . $state['Source']['entityid']); return; } - foreach ($request['Attributes'] as $k => $v) { + foreach ($state['Attributes'] as $k => $v) { if (!is_array($v)) { continue; } @@ -105,22 +105,22 @@ class CardinalitySingle extends Auth\ProcessingFilter } if (in_array($k, $this->singleValued)) { - $request['core:cardinality:errorAttributes'][$k] = [count($v), '0 ≤ n ≤ 1']; + $state['core:cardinality:errorAttributes'][$k] = [count($v), '0 ≤ n ≤ 1']; continue; } if (in_array($k, $this->firstValue)) { - $request['Attributes'][$k] = [array_shift($v)]; + $state['Attributes'][$k] = [array_shift($v)]; continue; } if (in_array($k, $this->flatten)) { - $request['Attributes'][$k] = [implode($this->flattenWith, $v)]; + $state['Attributes'][$k] = [implode($this->flattenWith, $v)]; continue; } } /* abort if we found a problematic attribute */ - if (array_key_exists('core:cardinality:errorAttributes', $request)) { - $id = Auth\State::saveState($request, 'core:cardinality'); + if (array_key_exists('core:cardinality:errorAttributes', $state)) { + $id = Auth\State::saveState($state, 'core:cardinality'); $url = Module::getModuleURL('core/cardinality_error.php'); $this->httpUtils->redirectTrustedURL($url, ['StateId' => $id]); return; diff --git a/modules/core/lib/Auth/Process/GenerateGroups.php b/modules/core/lib/Auth/Process/GenerateGroups.php index 2a8eadef7a1930a5e7e180ddfbd60e7954983aea..89e8b4c21cb25fde994d6c513730bb5fb6ff6956 100644 --- a/modules/core/lib/Auth/Process/GenerateGroups.php +++ b/modules/core/lib/Auth/Process/GenerateGroups.php @@ -56,14 +56,14 @@ class GenerateGroups extends Auth\ProcessingFilter /** * Apply filter to add groups attribute. * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); $groups = []; - $attributes = &$request['Attributes']; + $attributes = &$state['Attributes']; $realm = self::getRealm($attributes); if ($realm !== null) { diff --git a/modules/core/lib/Auth/Process/LanguageAdaptor.php b/modules/core/lib/Auth/Process/LanguageAdaptor.php index c621172e6f61129548a03c457c34b3618b2c236d..d38588e2eaadce68202b9b4556128bb70eabb473 100644 --- a/modules/core/lib/Auth/Process/LanguageAdaptor.php +++ b/modules/core/lib/Auth/Process/LanguageAdaptor.php @@ -41,13 +41,13 @@ class LanguageAdaptor extends Auth\ProcessingFilter * * Add or replace existing attributes with the configured values. * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); - $attributes = &$request['Attributes']; + $attributes = &$state['Attributes']; $attrlang = null; if (array_key_exists($this->langattr, $attributes)) { @@ -68,7 +68,7 @@ class LanguageAdaptor extends Auth\ProcessingFilter Language::setLanguageCookie($attrlang); } elseif (!isset($attrlang) && isset($lang)) { // Language set in cookie, but not in attribute. Update attribute - $request['Attributes'][$this->langattr] = [$lang]; + $state['Attributes'][$this->langattr] = [$lang]; } } } diff --git a/modules/core/lib/Auth/Process/PHP.php b/modules/core/lib/Auth/Process/PHP.php index 15428a461a4cce69e45f34cc1704fe8c58d1df7c..d2005eec3667ba21cd423fa28969e4c7146880a1 100644 --- a/modules/core/lib/Auth/Process/PHP.php +++ b/modules/core/lib/Auth/Process/PHP.php @@ -46,13 +46,11 @@ class PHP extends Auth\ProcessingFilter /** * Apply the PHP code to the attributes. * - * @param array &$request The current request - * - * @scrutinizer ignore-unused + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); /** * @param array &$attributes @@ -64,6 +62,6 @@ class PHP extends Auth\ProcessingFilter ) { eval($this->code); }; - $function($request['Attributes'], $request); + $function($state['Attributes'], $state); } } diff --git a/modules/core/lib/Auth/Process/ScopeAttribute.php b/modules/core/lib/Auth/Process/ScopeAttribute.php index 18955f9f64fbc171c3857504f4f3cf49dca18025..aec51485d558bab25749c58de9c564abf12e0ac4 100644 --- a/modules/core/lib/Auth/Process/ScopeAttribute.php +++ b/modules/core/lib/Auth/Process/ScopeAttribute.php @@ -67,13 +67,13 @@ class ScopeAttribute extends Auth\ProcessingFilter /** * Apply this filter to the request. * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); - $attributes = &$request['Attributes']; + $attributes = &$state['Attributes']; if (!isset($attributes[$this->scopeAttribute])) { return; diff --git a/modules/core/lib/Auth/Process/ScopeFromAttribute.php b/modules/core/lib/Auth/Process/ScopeFromAttribute.php index 7734cacb42b2ba35107cb8aff953e2dbe86ec710..be54edaea628360f2633f3bdeea64bd1e0a3896f 100644 --- a/modules/core/lib/Auth/Process/ScopeFromAttribute.php +++ b/modules/core/lib/Auth/Process/ScopeFromAttribute.php @@ -61,13 +61,13 @@ class ScopeFromAttribute extends Auth\ProcessingFilter /** * Apply this filter. * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); - $attributes = &$request['Attributes']; + $attributes = &$state['Attributes']; if (!isset($attributes[$this->sourceAttribute])) { return; diff --git a/modules/exampleauth/lib/Auth/Source/External.php b/modules/exampleauth/lib/Auth/Source/External.php index 2e8830fdf688ab2860df457e08a72c0d2723fb34..d369fc71348def32ee15b3d788ca20115add94a0 100644 --- a/modules/exampleauth/lib/Auth/Source/External.php +++ b/modules/exampleauth/lib/Auth/Source/External.php @@ -195,7 +195,7 @@ class External extends Auth\Source * First we need to restore the $state-array. We should have the identifier for * it in the 'State' request parameter. */ - if (!$request->has('State')) { + if (!$request->query->has('State')) { throw new Error\BadRequest('Missing "State" parameter.'); } diff --git a/modules/saml/lib/Auth/Process/ExpectedAuthnContextClassRef.php b/modules/saml/lib/Auth/Process/ExpectedAuthnContextClassRef.php index 2ffd641a6695540280fa9b5c842a93311d743f61..103d618e7a76acd7d9376e5845680f0e7879241c 100644 --- a/modules/saml/lib/Auth/Process/ExpectedAuthnContextClassRef.php +++ b/modules/saml/lib/Auth/Process/ExpectedAuthnContextClassRef.php @@ -69,17 +69,16 @@ class ExpectedAuthnContextClassRef extends ProcessingFilter /** - * - * @param array &$request The current request + * @param array &$state The current request */ - public function process(array &$request): void + public function process(array &$state): void { - Assert::keyExists($request, 'Attributes'); + Assert::keyExists($state, 'Attributes'); - $this->AuthnContextClassRef = $request['saml:sp:State']['saml:sp:AuthnContext']; + $this->AuthnContextClassRef = $state['saml:sp:State']['saml:sp:AuthnContext']; if (!in_array($this->AuthnContextClassRef, $this->accepted, true)) { - $this->unauthorized($request); + $this->unauthorized($state); } } @@ -94,16 +93,16 @@ class ExpectedAuthnContextClassRef extends ProcessingFilter * thinking in case a "chained" ACL is needed, more complex * permission logic. * - * @param array $request + * @param array $state */ - protected function unauthorized(array &$request): void + protected function unauthorized(array &$state): void { Logger::error( 'ExpectedAuthnContextClassRef: Invalid authentication context: ' . strval($this->AuthnContextClassRef) . '. Accepted values are: ' . var_export($this->accepted, true) ); - $id = Auth\State::saveState($request, 'saml:ExpectedAuthnContextClassRef:unauthorized'); + $id = Auth\State::saveState($state, 'saml:ExpectedAuthnContextClassRef:unauthorized'); $url = Module::getModuleURL( 'saml/sp/wrong_authncontextclassref.php' ); diff --git a/modules/saml/lib/Auth/Process/FilterScopes.php b/modules/saml/lib/Auth/Process/FilterScopes.php index b0fb75237d7fa7e4384af1bdc89fb6ad9436b655..13b9753702c5d33f4597507b3e447e5ccb3c83cc 100644 --- a/modules/saml/lib/Auth/Process/FilterScopes.php +++ b/modules/saml/lib/Auth/Process/FilterScopes.php @@ -43,27 +43,27 @@ class FilterScopes extends ProcessingFilter /** * This method applies the filter, removing any values * - * @param array &$request the current request + * @param array &$state the current request */ - public function process(array &$request): void + public function process(array &$state): void { - $src = $request['Source']; + $src = $state['Source']; $validScopes = []; $host = ''; if (array_key_exists('scope', $src) && is_array($src['scope']) && !empty($src['scope'])) { $validScopes = $src['scope']; } else { - $ep = Utils\Config\Metadata::getDefaultEndpoint($request['Source']['SingleSignOnService']); + $ep = Utils\Config\Metadata::getDefaultEndpoint($state['Source']['SingleSignOnService']); $host = parse_url($ep['Location'], PHP_URL_HOST) ?? ''; } foreach ($this->scopedAttributes as $attribute) { - if (!isset($request['Attributes'][$attribute])) { + if (!isset($state['Attributes'][$attribute])) { continue; } - $values = $request['Attributes'][$attribute]; + $values = $state['Attributes'][$attribute]; $newValues = []; foreach ($values as $value) { @list(, $scope) = explode('@', $value, 2); @@ -83,9 +83,9 @@ class FilterScopes extends ProcessingFilter if (empty($newValues)) { Logger::warning("No suitable values for attribute '$attribute', removing it."); - unset($request['Attributes'][$attribute]); // remove empty attributes + unset($state['Attributes'][$attribute]); // remove empty attributes } else { - $request['Attributes'][$attribute] = $newValues; + $state['Attributes'][$attribute] = $newValues; } } } diff --git a/modules/saml/lib/Error.php b/modules/saml/lib/Error.php index 7a4655470615f4d24b028e88cce6310136377baa..d54d40dfe3bb65315210ca1d8710d71905fff2d3 100644 --- a/modules/saml/lib/Error.php +++ b/modules/saml/lib/Error.php @@ -108,20 +108,20 @@ class Error extends \SimpleSAML\Error\Exception * This function attempts to create a SAML2 error with the appropriate * status codes from an arbitrary exception. * - * @param \Throwable $exception The original exception. + * @param \Throwable $e The original exception. * @return \SimpleSAML\Error\Exception The new exception. */ - public static function fromException(Throwable $exception): \SimpleSAML\Error\Exception + public static function fromException(Throwable $e): \SimpleSAML\Error\Exception { - if ($exception instanceof \SimpleSAML\Module\saml\Error) { + if ($e instanceof \SimpleSAML\Module\saml\Error) { // Return the original exception unchanged - return $exception; + return $e; } else { $e = new self( \SAML2\Constants::STATUS_RESPONDER, null, - get_class($exception) . ': ' . $exception->getMessage(), - $exception + get_class($e) . ': ' . $e->getMessage(), + $e ); } diff --git a/modules/saml/templates/proxy/invalid_session.twig b/modules/saml/templates/proxy/invalid_session.twig index f9acc7a9881e7b12c7b5ff432b80b091ee6dc6c7..593adca27ace9b143b6209ab459279102453ac0d 100644 --- a/modules/saml/templates/proxy/invalid_session.twig +++ b/modules/saml/templates/proxy/invalid_session.twig @@ -3,7 +3,7 @@ {% block content %} <h2>{{ 'Invalid Identity Provider'|trans }}</h2> - <p>{{ 'You already have a valid session with an identity provider (<em>%IDP%</em>) that is not accepted by <em>%SP%</em>. Would you like to log out from your existing session and log in again with another identity provider?'|trans({"%IDP%": idp_name, "%SP%": sp_name}, "app")|raw</p> + <p>{{ 'You already have a valid session with an identity provider (<em>%IDP%</em>) that is not accepted by <em>%SP%</em>. Would you like to log out from your existing session and log in again with another identity provider?'|trans({"%IDP%": idp_name|translateFromArray|default(idp_entityid), "%SP%": sp_name|translateFromArray|default(sp_entityid)}, "app")|raw</p> <form method="post" action="?"> <input type="hidden" name="AuthState" value="{{ AuthState|escape('html') }}" /> <input type="submit" name="continue" value="{{ 'Yes, continue'|trans }}" /> diff --git a/modules/saml/www/proxy/invalid_session.php b/modules/saml/www/proxy/invalid_session.php index 30c18095d309b9ece4d2a5ba71ad6a2207e440d7..9dd31b5250cd9e1dd9846df3dfa86c57a2d8f2c9 100644 --- a/modules/saml/www/proxy/invalid_session.php +++ b/modules/saml/www/proxy/invalid_session.php @@ -56,21 +56,19 @@ $idpmdcfg = $state['saml:sp:IdPMetadata']; /** @var \SimpleSAML\Configuration $idpmdcfg */ $idpmd = $idpmdcfg->toArray(); if (array_key_exists('name', $idpmd)) { - $template->data['idp_name'] = $translator->getPreferredTranslation($idpmd['name']); + $template->data['idp_name'] = $idpmd['name']; } elseif (array_key_exists('OrganizationDisplayName', $idpmd)) { - $template->data['idp_name'] = $translator->getPreferredTranslation($idpmd['OrganizationDisplayName']); -} else { - $template->data['idp_name'] = $idpmd['entityid']; + $template->data['idp_name'] = $idpmd['OrganizationDisplayName']; } +$template->data['idp_entityid'] = $idpmd['entityid']; // get the name of the SP $spmd = $state['SPMetadata']; if (array_key_exists('name', $spmd)) { - $template->data['sp_name'] = $translator->getPreferredTranslation($spmd['name']); + $template->data['sp_name'] = $spmd['name']; } elseif (array_key_exists('OrganizationDisplayName', $spmd)) { - $template->data['sp_name'] = $translator->getPreferredTranslation($spmd['OrganizationDisplayName']); -} else { - $template->data['sp_name'] = $spmd['entityid']; + $template->data['sp_name'] = $spmd['OrganizationDisplayName']; } +$template->data['sp_entityid'] = $spmd['entityid']; $template->send();