diff --git a/.gitattributes b/.gitattributes
index 1d18ab03186051ec4b5d37585097660ea1da3b00..5e65350564c396c45a9f01d76ad3b9a23e5406e3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7,5 +7,4 @@
 .editorconfig export-ignore
 .gitattributes export-ignore
 .gitignore export-ignore
-.travis.yml export-ignore
 
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index 98c9c344eca0511cf8758265f783395efe364d1a..3a855ad06ee3f0fe94aa251980525abb5ae9de07 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -23,7 +23,7 @@ jobs:
           php-version: ${{ matrix.php-versions }}
           extensions: mbstring, mysql, pdo, pdo_sqlite, xml
           tools: composer:v2
-          coverage: pcov
+          coverage: xdebug
 
       - name: Setup problem matchers for PHP
         run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
diff --git a/README.md b/README.md
index 80c97018cc3bb48b76bb5864b7a2fdd3513dc21e..cbd6cb899db4a70cea7d32060615c4ce6ce4ea67 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@ SimpleSAMLphp
 =============
 ![Build Status](https://github.com/simplesamlphp/simplesamlphp/workflows/CI/badge.svg?branch=master)
 [![Coverage Status](https://codecov.io/gh/simplesamlphp/simplesamlphp/branch/master/graph/badge.svg)](https://codecov.io/gh/simplesamlphp/simplesamlphp)
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/simplesamlphp/simplesamlphp/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/simplesamlphp/?branch=master)
 [![BrowserStack Status](https://automate.browserstack.com/badge.svg?badge_key=LzlCL29sZEVDRXJpdGtxZUdITFA3YjYyUFBBYkVVZDVDcG1YZXRaN2pvTT0tLVhCNzkwVUNGVFVjVFVicUg0R1BNR0E9PQ==--f9efb6f330bd98dd6e3c7b816ac2f0982275a872)](https://automate.browserstack.com/public-build/LzlCL29sZEVDRXJpdGtxZUdITFA3YjYyUFBBYkVVZDVDcG1YZXRaN2pvTT0tLVhCNzkwVUNGVFVjVFVicUg0R1BNR0E9PQ==--f9efb6f330bd98dd6e3c7b816ac2f0982275a872)
 
 
diff --git a/TESTING.md b/TESTING.md
index c46cf4956c5c3aab11f039604305bcb3b55b7777..8b24c2fe9cc0bcd78ff8dc5dc4a982aa2ca102ed 100644
--- a/TESTING.md
+++ b/TESTING.md
@@ -64,7 +64,6 @@ the old version installed by composer
 ./vendor/bin/phpunit -c ./phpunit.xml
 ```
 
-All the tests are run by our *continuous integration* platform,
-[travis](https://travis-ci.org/simplesamlphp/simplesamlphp). If you are
-submitting a pull request, Travis will run your tests and notify whether
-your code builds or not according to them.
+All the tests are run by our *continuous integration* platform using GitHub
+Actions. If you are submitting a pull request, GitHub Actions will run your
+tests and notify whether your code builds or not according to them.
diff --git a/bin/build-release.sh b/bin/build-release.sh
index 87ee08570998bc4e8c776d0660f3739f6a8458f9..9ae7eac0e1007670d87c0684c2eacf5100130755 100755
--- a/bin/build-release.sh
+++ b/bin/build-release.sh
@@ -60,8 +60,8 @@ rm -rf "$TARGET/node_modules"
 rm "$TARGET/www/assets/js/stylesheet.js"*
 rm "$TARGET/.editorconfig"
 rm "$TARGET/.gitattributes"
+rm -r "$TARGET/.github"
 rm "$TARGET/.php_cs.dist"
-rm "$TARGET/.travis.yml"
 rm "$TARGET/codecov.yml"
 rm "$TARGET/psalm.xml"
 rm "$TARGET"/{,modules}/.gitignore
diff --git a/config-templates/config.php b/config-templates/config.php
index 50e03fdcc02401a32c49e0be25d52ce0190e10d2..db59453a96918e5fbe0ffc027bbe279162b451a1 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -470,7 +470,7 @@ $config = [
      ***********/
 
     /*
-     * Configuration to override module enabling/disabling.
+     * Configuration for enabling/disabling modules. By default the 'core' and 'saml' modules are enabled.
      *
      * Example:
      *
@@ -751,7 +751,7 @@ $config = [
          * ],
          *
          * establishing that if a translation for the "no" language code is
-         * not available, we look for translations in "nb" (Norwegian BokmĂĄl),
+         * not available, we look for translations in "nb",
          * and so on, in that order.
          */
         'priorities' => [
@@ -971,7 +971,7 @@ $config = [
             'type'          => 'saml20-idp-SSO',
         ],
 
-        /* When called without parameters, it will fallback to filter attributes ‹the old way›
+        /* When called without parameters, it will fallback to filter attributes 'the old way'
          * by checking the 'attributes' parameter in metadata on IdP hosted and SP remote.
          */
         50 => 'core:AttributeLimit',
diff --git a/docs/simplesamlphp-changelog.md b/docs/simplesamlphp-changelog.md
index 3f69766cedb1b554b331f169a7a8f5f29190a277..3e1f8ec3a8debf367b5e22bca99f60c8f3763d87 100644
--- a/docs/simplesamlphp-changelog.md
+++ b/docs/simplesamlphp-changelog.md
@@ -13,14 +13,44 @@ See the upgrade notes for specific information about upgrading.
   * Old-style PHP templates were removed
   * Old-style dictionaries were removed
 
+## Version 1.19.1
+
 Released TBD
 
+  * Fixed a bug in the Artifact Resolution Service (#1428)
+  * Fixed compatibility with Composer pre 1.8.5 (Debian 10) (#1427)
+  * Updated npm dependencies up to February 1, 2021
+
+### memcacheMonitor
+  * Fix a bug in the Twig-template that causes an exception on newer Twig-versions
+
+### negotiate
+  * Fix a bug that was breaking the module when using the old UI
+
+### statistics
+  * Fix a bug in the Twig-template that causes an exception on newer Twig-versions
+
 ## Version 1.19.0
 
-Released TBD
+Released 2021-01-21
 
   * This version will be the last of the 1.x branch and will provide a migration path to our new
-    templating system, routing system, translation system and hooks.
+    templating system, routing system and translation system.
+  * SAML 1 / Shib 1.3 support is now marked deprecated and will be removed in SimpleSAMLphp 2.0.
+  * Raised minimum PHP version to 7.1
+  * Dropped support for Symfony 3.x
+  * Update the SAML2 library dependency to 4.1.9
+  * Fix a bug where SSP wouldn't write to the tmp-directory if it didn't own it, but could write to it (#1314)
+  * Fixed several bugs in saml:NameIDAttribute (#1245)
+  * Fix artifact resolution (#1343)
+  * Allow additional audiences to be specified (#1345)
+  * Allow configurable ProviderName (#1348)
+  * Support saml:Extensions in saml:SP authsources (#1349)
+  * The `attributename`-setting in the core:TargetedID authproc-filter has been deprecated in
+    favour of the `identifyingAttribute`-setting.
+  * Filter multiauth authentication sources from SP using AuthnContextClassRef (#1362)
+  * Allow easy enabling of SameSite = 'None' (#1382)
+  * Do not accept the hashed admin password for authentication (#1418)
 
 ## Version 1.18.8
 
diff --git a/lib/SimpleSAML/Auth/AuthenticationFactory.php b/lib/SimpleSAML/Auth/AuthenticationFactory.php
index e59bac61bb05a5ee668b68ea955a5315429d089b..e5997b0e634aa6d95b43fa3b7754992fe4156a5f 100644
--- a/lib/SimpleSAML/Auth/AuthenticationFactory.php
+++ b/lib/SimpleSAML/Auth/AuthenticationFactory.php
@@ -13,10 +13,10 @@ use SimpleSAML\Session;
 class AuthenticationFactory
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
diff --git a/lib/SimpleSAML/Auth/ProcessingChain.php b/lib/SimpleSAML/Auth/ProcessingChain.php
index 65a8fcd029cdd124d35b21c61afb62d7f953623d..a3612ff1981c85583738f14832f1e12f037a1d57 100644
--- a/lib/SimpleSAML/Auth/ProcessingChain.php
+++ b/lib/SimpleSAML/Auth/ProcessingChain.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace SimpleSAML\Auth;
 
+use Exception;
 use SimpleSAML\Assert\Assert;
 use SimpleSAML\Configuration;
 use SimpleSAML\Error;
@@ -45,7 +46,7 @@ class ProcessingChain
     /**
      * All authentication processing filters, in the order they should be applied.
      */
-    private $filters;
+    private array $filters = [];
 
 
     /**
@@ -58,8 +59,6 @@ class ProcessingChain
      */
     public function __construct(array $idpMetadata, array $spMetadata, string $mode = 'idp')
     {
-        $this->filters = [];
-
         $config = Configuration::getInstance();
         $configauthproc = $config->getArray('authproc.' . $mode, null);
 
@@ -125,7 +124,7 @@ class ProcessingChain
             }
 
             if (!is_array($filter)) {
-                throw new \Exception('Invalid authentication processing filter configuration: ' .
+                throw new Exception('Invalid authentication processing filter configuration: ' .
                     'One of the filters wasn\'t a string or an array.');
             }
 
@@ -147,7 +146,7 @@ class ProcessingChain
     private static function parseFilter(array $config, int $priority): ProcessingFilter
     {
         if (!array_key_exists('class', $config)) {
-            throw new \Exception('Authentication processing filter without name given.');
+            throw new Exception('Authentication processing filter without name given.');
         }
 
         $className = Module::resolveClass(
@@ -200,7 +199,7 @@ class ProcessingChain
         } catch (Error\Exception $e) {
             // No need to convert the exception
             throw $e;
-        } catch (\Exception $e) {
+        } catch (Exception $e) {
             /*
              * To be consistent with the exception we return after an redirect,
              * we convert this exception before returning it.
@@ -231,7 +230,7 @@ class ProcessingChain
                 $filter->process($state);
             } catch (Error\Exception $e) {
                 State::throwException($state, $e);
-            } catch (\Exception $e) {
+            } catch (Exception $e) {
                 $e = new Error\UnserializableException($e);
                 State::throwException($state, $e);
             }
diff --git a/lib/SimpleSAML/Auth/ProcessingFilter.php b/lib/SimpleSAML/Auth/ProcessingFilter.php
index 90442a5b2cfa91e6473b39a63b028c149622d962..139d66816c8a77cf03e07984ee8060af47eee7ba 100644
--- a/lib/SimpleSAML/Auth/ProcessingFilter.php
+++ b/lib/SimpleSAML/Auth/ProcessingFilter.php
@@ -32,9 +32,9 @@ abstract class ProcessingFilter
      * The priority can be any integer. The default for most filters is 50. Filters may however
      * specify their own default, if they typically should be amongst the first or the last filters.
      *
-     * The prioroty can also be overridden by the user by specifying the '%priority' option.
+     * The priority can also be overridden by the user by specifying the '%priority' option.
      */
-    public $priority = 50;
+    public int $priority = 50;
 
 
     /**
diff --git a/lib/SimpleSAML/Auth/Simple.php b/lib/SimpleSAML/Auth/Simple.php
index 1d435a7efb31d2465d2dd3c39e05b1afb212db6b..6e0ac4e07c94364824d4ff32412cbc2debcf3586 100644
--- a/lib/SimpleSAML/Auth/Simple.php
+++ b/lib/SimpleSAML/Auth/Simple.php
@@ -24,13 +24,13 @@ class Simple
      *
      * @var string
      */
-    protected $authSource;
+    protected string $authSource;
 
     /** @var \SimpleSAML\Configuration */
-    protected $app_config;
+    protected Configuration $app_config;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
diff --git a/lib/SimpleSAML/Auth/Source.php b/lib/SimpleSAML/Auth/Source.php
index 3f52d31111c5e73f19ddfcb83d5d8a5472ded7a5..80617d427cf25b70815a5f80daee898817559219 100644
--- a/lib/SimpleSAML/Auth/Source.php
+++ b/lib/SimpleSAML/Auth/Source.php
@@ -28,7 +28,7 @@ abstract class Source
      *
      * @var string
      */
-    protected $authId;
+    protected string $authId = '';
 
 
     /**
diff --git a/lib/SimpleSAML/Auth/State.php b/lib/SimpleSAML/Auth/State.php
index 175fd9494e5f0cd4c7df787fed6c30470311f5c7..1e7153ea5c57a6b6c4e70243d661242a58463a08 100644
--- a/lib/SimpleSAML/Auth/State.php
+++ b/lib/SimpleSAML/Auth/State.php
@@ -101,7 +101,7 @@ class State
     /**
      * State timeout.
      */
-    private static $stateTimeout = null;
+    private static ?int $stateTimeout = null;
 
 
     /**
diff --git a/lib/SimpleSAML/Command/RouterDebugCommand.php b/lib/SimpleSAML/Command/RouterDebugCommand.php
index b5610c797dff3aa415330de1c352a1a92c5d5056..0df7febce3d4c5f6c3cc95042aaf40bbe573124f 100644
--- a/lib/SimpleSAML/Command/RouterDebugCommand.php
+++ b/lib/SimpleSAML/Command/RouterDebugCommand.php
@@ -20,9 +20,9 @@ class RouterDebugCommand extends Command
     protected static $defaultName = 'debug:router';
 
     /**
-     * @var RouterInterface
+     * @var \Symfony\Component\Routing\RouterInterface
      */
-    private $router;
+    private RouterInterface $router;
 
 
     /**
diff --git a/lib/SimpleSAML/Configuration.php b/lib/SimpleSAML/Configuration.php
index d562448cbf35da57f431b1b233b356a70c80c0b8..78e1cf80e067a0617b25b7ab058eb8eb6c35ee2e 100644
--- a/lib/SimpleSAML/Configuration.php
+++ b/lib/SimpleSAML/Configuration.php
@@ -31,9 +31,9 @@ class Configuration implements Utils\ClearableState
     /**
      * Associative array with mappings from instance-names to configuration objects.
      *
-     * @var array
+     * @var array<string, \SimpleSAML\Configuration>
      */
-    private static $instance = [];
+    private static array $instance = [];
 
     /**
      * Configuration directories.
@@ -41,9 +41,9 @@ class Configuration implements Utils\ClearableState
      * This associative array contains the mappings from configuration sets to
      * configuration directories.
      *
-     * @var array
+     * @var array<string, string>
      */
-    private static $configDirs = [];
+    private static array $configDirs = [];
 
     /**
      * Cache of loaded configuration files.
@@ -52,28 +52,28 @@ class Configuration implements Utils\ClearableState
      *
      * @var array
      */
-    private static $loadedConfigs = [];
+    private static array $loadedConfigs = [];
 
     /**
      * The configuration array.
      *
      * @var array
      */
-    private $configuration;
+    private array $configuration;
 
     /**
      * The location which will be given when an error occurs.
      *
      * @var string
      */
-    private $location;
+    private string $location;
 
     /**
      * The file this configuration was loaded from.
      *
      * @var string|null
      */
-    private $filename = null;
+    private ?string $filename = null;
 
     /**
      * Initializes a configuration from the given array.
diff --git a/lib/SimpleSAML/Database.php b/lib/SimpleSAML/Database.php
index 8a076654dae269a2256a0305c1c51bdec0d5bed5..ab5ddc2c71c1eac8a11140dfe315b442685331a8 100644
--- a/lib/SimpleSAML/Database.php
+++ b/lib/SimpleSAML/Database.php
@@ -27,28 +27,30 @@ class Database
 {
     /**
      * This variable holds the instance of the session - Singleton approach.
+     * @var \SimpleSAML\Database[]
      */
-    private static $instance = [];
+    private static array $instance = [];
 
     /**
      * PDO Object for the Primary database server
      */
-    private $dbPrimary;
+    private PDO $dbPrimary;
 
     /**
      * Array of PDO Objects for configured database secondaries
+     * @var \PDO[]
      */
-    private $dbSecondaries = [];
+    private array $dbSecondaries = [];
 
     /**
      * Prefix to apply to the tables
      */
-    private $tablePrefix;
+    private string $tablePrefix;
 
     /**
      * Array with information on the last error occurred.
      */
-    private $lastError;
+    private array $lastError = [];
 
 
     /**
diff --git a/lib/SimpleSAML/Error/AuthSource.php b/lib/SimpleSAML/Error/AuthSource.php
index 9ee3a50d76852c860bcc43383df46082b1e9246a..1de3be5935c0768bce2ac4070a97918b7ee7025b 100644
--- a/lib/SimpleSAML/Error/AuthSource.php
+++ b/lib/SimpleSAML/Error/AuthSource.php
@@ -20,13 +20,13 @@ class AuthSource extends Error
      * Authsource module name
      * @var string
      */
-    private $authsource;
+    private string $authsource;
 
     /**
      * Reason why this request was invalid.
      * @var string
      */
-    private $reason;
+    private string $reason;
 
 
     /**
diff --git a/lib/SimpleSAML/Error/BadRequest.php b/lib/SimpleSAML/Error/BadRequest.php
index ed491bd0eccfbdccc0128b5ed1746ce731302525..2b3c2c8e0dd29422afceb740d0fb39bb59efd1de 100644
--- a/lib/SimpleSAML/Error/BadRequest.php
+++ b/lib/SimpleSAML/Error/BadRequest.php
@@ -21,7 +21,7 @@ class BadRequest extends Error
      * Reason why this request was invalid.
      * @var string
      */
-    private $reason;
+    private string $reason;
 
 
     /**
diff --git a/lib/SimpleSAML/Error/ConfigurationError.php b/lib/SimpleSAML/Error/ConfigurationError.php
index 4fdcdded368a5177f56601c7fb52bc63633320f2..bc0d9c261c130973c7c2e68ecb28317294e5fe73 100644
--- a/lib/SimpleSAML/Error/ConfigurationError.php
+++ b/lib/SimpleSAML/Error/ConfigurationError.php
@@ -17,14 +17,14 @@ class ConfigurationError extends Error
      *
      * @var null|string
      */
-    protected $reason;
+    protected ?string $reason;
 
     /**
      * The configuration file that caused this exception.
      *
      * @var null|string
      */
-    protected $config_file;
+    protected ?string $config_file;
 
 
     /**
diff --git a/lib/SimpleSAML/Error/CriticalConfigurationError.php b/lib/SimpleSAML/Error/CriticalConfigurationError.php
index 14907a5aba43199ff2d425dd202a09d269b48bfe..b48581cb43db5777b37dc0b398d1de4c3eeffee6 100644
--- a/lib/SimpleSAML/Error/CriticalConfigurationError.php
+++ b/lib/SimpleSAML/Error/CriticalConfigurationError.php
@@ -34,7 +34,7 @@ class CriticalConfigurationError extends ConfigurationError
      *
      * @var array
      */
-    private static $minimum_config = [
+    private static array $minimum_config = [
         'logging.handler' => 'errorlog',
         'logging.level'  => Logger::DEBUG,
         'errorreporting' => false,
diff --git a/lib/SimpleSAML/Error/Error.php b/lib/SimpleSAML/Error/Error.php
index 2d7375f5b4d68a1beec97069314f0b906b2a95f5..e376027dfa33c828c261dfc30c9fabfb8545e812 100644
--- a/lib/SimpleSAML/Error/Error.php
+++ b/lib/SimpleSAML/Error/Error.php
@@ -25,49 +25,49 @@ class Error extends Exception
      *
      * @var string
      */
-    private $errorCode;
+    private string $errorCode;
 
     /**
      * The http code.
      *
      * @var integer
      */
-    protected $httpCode = 500;
+    protected int $httpCode = 500;
 
     /**
      * The error title tag in dictionary.
      *
      * @var string
      */
-    private $dictTitle;
+    private string $dictTitle;
 
     /**
      * The error description tag in dictionary.
      *
      * @var string
      */
-    private $dictDescr;
+    private string $dictDescr;
 
     /**
      * The name of module that threw the error.
      *
      * @var string|null
      */
-    private $module = null;
+    private ?string $module = null;
 
     /**
      * The parameters for the error.
      *
      * @var array
      */
-    private $parameters;
+    private array $parameters;
 
     /**
      * Name of custom include template for the error.
      *
      * @var string|null
      */
-    protected $includeTemplate = null;
+    protected ?string $includeTemplate = null;
 
 
     /**
diff --git a/lib/SimpleSAML/Error/Exception.php b/lib/SimpleSAML/Error/Exception.php
index 15d4fa644cf066fa8ef71a75194543bd6f9caed8..c0b339fd6ff049f1057bfa80387d869d06f575c5 100644
--- a/lib/SimpleSAML/Error/Exception.php
+++ b/lib/SimpleSAML/Error/Exception.php
@@ -27,14 +27,14 @@ class Exception extends \Exception
      *
      * @var array<int, string>
      */
-    private $backtrace = [];
+    private array $backtrace = [];
 
     /**
      * The cause of this exception.
      *
      * @var \SimpleSAML\Error\Exception|null
      */
-    private $cause = null;
+    private ?Exception $cause = null;
 
 
     /**
diff --git a/lib/SimpleSAML/Error/NotFound.php b/lib/SimpleSAML/Error/NotFound.php
index af96fc5f677a8f9bb5fd5adb4c2879815b17a46d..f7f180463a0dff1a0b57ae6514539030f0139e1a 100644
--- a/lib/SimpleSAML/Error/NotFound.php
+++ b/lib/SimpleSAML/Error/NotFound.php
@@ -21,7 +21,7 @@ class NotFound extends Error
     /**
      * Reason why the given page could not be found.
      */
-    private $reason;
+    private ?string $reason;
 
 
     /**
diff --git a/lib/SimpleSAML/Error/UnserializableException.php b/lib/SimpleSAML/Error/UnserializableException.php
index 14ea1d7b415f599e2bceb13a2b8f912c3f95c70e..d843f70428699a2c2cd4afb0bb7fef184ef010a6 100644
--- a/lib/SimpleSAML/Error/UnserializableException.php
+++ b/lib/SimpleSAML/Error/UnserializableException.php
@@ -27,7 +27,7 @@ class UnserializableException extends Exception
      *
      * @var string
      */
-    private $class;
+    private string $class;
 
 
     /**
diff --git a/lib/SimpleSAML/HTTP/RunnableResponse.php b/lib/SimpleSAML/HTTP/RunnableResponse.php
index 32938c1bba7f3002aeba1b1d85ec86946527b4cc..0e67003ea31f712767a14b5007b297386376d28d 100644
--- a/lib/SimpleSAML/HTTP/RunnableResponse.php
+++ b/lib/SimpleSAML/HTTP/RunnableResponse.php
@@ -17,7 +17,7 @@ use Symfony\Component\HttpFoundation\Response;
 class RunnableResponse extends Response
 {
     /** @var array */
-    protected $arguments;
+    protected array $arguments;
 
     /** @var callable */
     protected $callable;
diff --git a/lib/SimpleSAML/IdP.php b/lib/SimpleSAML/IdP.php
index 876e4d0eda8514d5b8d62f050a98c3d5334c860f..c5f983791fbdb73beb241063846a65f00c4d54b4 100644
--- a/lib/SimpleSAML/IdP.php
+++ b/lib/SimpleSAML/IdP.php
@@ -7,6 +7,7 @@ namespace SimpleSAML;
 use SAML2\Constants;
 use SimpleSAML\Assert\Assert;
 use SimpleSAML\Auth;
+use SimpleSAML\Configuration;
 use SimpleSAML\IdP\IFrameLogoutHandler;
 use SimpleSAML\IdP\LogoutHandlerInterface;
 use SimpleSAML\IdP\TraditionalLogoutHandler;
@@ -30,14 +31,14 @@ class IdP
      *
      * @var array
      */
-    private static $idpCache = [];
+    private static array $idpCache = [];
 
     /**
      * The identifier for this IdP.
      *
      * @var string
      */
-    private $id;
+    private string $id;
 
     /**
      * The "association group" for this IdP.
@@ -47,21 +48,21 @@ class IdP
      *
      * @var string
      */
-    private $associationGroup;
+    private string $associationGroup;
 
     /**
      * The configuration for this IdP.
      *
-     * @var Configuration
+     * @var \SimpleSAML\Configuration
      */
-    private $config;
+    private Configuration $config;
 
     /**
      * Our authsource.
      *
-     * @var Auth\Simple
+     * @var \SimpleSAML\Auth\Simple
      */
-    private $authSource;
+    private Auth\Simple $authSource;
 
 
     /**
diff --git a/lib/SimpleSAML/IdP/IFrameLogoutHandler.php b/lib/SimpleSAML/IdP/IFrameLogoutHandler.php
index b7303a256f3e6662b5ae5374afee8617e6343fae..9cf2f30ff8ee5cac6913978ba347a8b83eb20ebb 100644
--- a/lib/SimpleSAML/IdP/IFrameLogoutHandler.php
+++ b/lib/SimpleSAML/IdP/IFrameLogoutHandler.php
@@ -26,7 +26,8 @@ class IFrameLogoutHandler implements LogoutHandlerInterface
      *
      * @var \SimpleSAML\IdP
      */
-    private $idp;
+    private IDP $idp;
+
 
     /**
      * LogoutIFrame constructor.
@@ -38,6 +39,7 @@ class IFrameLogoutHandler implements LogoutHandlerInterface
         $this->idp = $idp;
     }
 
+
     /**
      * Start the logout operation.
      *
diff --git a/lib/SimpleSAML/IdP/TraditionalLogoutHandler.php b/lib/SimpleSAML/IdP/TraditionalLogoutHandler.php
index cf6c2a63cdf7f14097737989e14ff3766c3969be..a22834aff93e636f4a1a3456f8a09cc4541ecac0 100644
--- a/lib/SimpleSAML/IdP/TraditionalLogoutHandler.php
+++ b/lib/SimpleSAML/IdP/TraditionalLogoutHandler.php
@@ -24,7 +24,7 @@ class TraditionalLogoutHandler implements LogoutHandlerInterface
      *
      * @var \SimpleSAML\IdP
      */
-    private $idp;
+    private IDP $idp;
 
 
     /**
diff --git a/lib/SimpleSAML/Kernel.php b/lib/SimpleSAML/Kernel.php
index 9a51df2c46e6477aebd1bb151453fd92bc07cfef..be7321a35b1b83d05b129f0827ce7f5d3509e8e0 100644
--- a/lib/SimpleSAML/Kernel.php
+++ b/lib/SimpleSAML/Kernel.php
@@ -26,7 +26,7 @@ class Kernel extends BaseKernel
     public const CONFIG_EXTS = '.{php,xml,yaml,yml}';
 
     /** @var string */
-    private $module;
+    private string $module;
 
 
     /**
diff --git a/lib/SimpleSAML/Locale/Language.php b/lib/SimpleSAML/Locale/Language.php
index eeaaaa890aa0eec388f5ad118b459d6486681178..347b41232e8b55cf4d2473c61709e61e4748fab1 100644
--- a/lib/SimpleSAML/Locale/Language.php
+++ b/lib/SimpleSAML/Locale/Language.php
@@ -19,50 +19,51 @@ class Language
 {
     /**
      * This is the default language map. It is used to map languages codes from the user agent to other language codes.
+     * @var array<string, string>
      */
-    private static $defaultLanguageMap = ['nb' => 'no'];
+    private static array $defaultLanguageMap = ['nb' => 'no'];
 
     /**
      * The configuration to use.
      *
      * @var \SimpleSAML\Configuration
      */
-    private $configuration;
+    private Configuration $configuration;
 
     /**
      * An array holding a list of languages available.
      *
-     * @var array
+     * @var string[]
      */
-    private $availableLanguages;
+    private array $availableLanguages;
 
     /**
      * The language currently in use.
      *
      * @var null|string
      */
-    private $language = null;
+    private ?string $language = null;
 
     /**
      * The language to use by default.
      *
      * @var string
      */
-    private $defaultLanguage;
+    private string $defaultLanguage;
 
     /**
      * An array holding a list of languages that are written from right to left.
      *
-     * @var array
+     * @var string[]
      */
-    private $rtlLanguages;
+    private array $rtlLanguages;
 
     /**
      * HTTP GET language parameter name.
      *
      * @var string
      */
-    private $languageParameterName;
+    private string $languageParameterName;
 
     /**
      * A custom function to use in order to determine the language in use.
@@ -77,9 +78,9 @@ class Language
      * with some charming SimpleSAML-specific variants...
      * that must remain before 2.0 due to backwards compatibility
      *
-     * @var array
+     * @var array<string, string>
      */
-    public static $language_names = [
+    public static array $language_names = [
         'no'    => 'BokmĂĄl', // Norwegian BokmĂĄl
         'nn'    => 'Nynorsk', // Norwegian Nynorsk
         'se'    => 'Sámegiella', // Northern Sami
@@ -128,9 +129,9 @@ class Language
     /**
      * A mapping of SSP languages to locales
      *
-     * @var array
+     * @var array<string, string>
      */
-    private $languagePosixMapping = [
+    private array $languagePosixMapping = [
         'no' => 'nb_NO',
         'nn' => 'nn_NO',
     ];
diff --git a/lib/SimpleSAML/Locale/Localization.php b/lib/SimpleSAML/Locale/Localization.php
index b28c54da3919e767c208b8fb8692d39abcec0520..6aaae8aa8f58d5eff7f860b9ef06cad8cffdc5e2 100644
--- a/lib/SimpleSAML/Locale/Localization.php
+++ b/lib/SimpleSAML/Locale/Localization.php
@@ -22,7 +22,7 @@ class Localization
      *
      * @var \SimpleSAML\Configuration
      */
-    private $configuration;
+    private Configuration $configuration;
 
     /**
      * The default gettext domain.
@@ -50,35 +50,35 @@ class Localization
      *
      * @var string
      */
-    private $localeDir;
+    private string $localeDir;
 
     /**
      * Where specific domains are stored
      *
      * @var array
      */
-    private $localeDomainMap = [];
+    private array $localeDomainMap = [];
 
     /**
      * Pointer to currently active translator
      *
      * @var \Gettext\Translator
      */
-    private $translator;
+    private Translator $translator;
 
     /**
      * Pointer to current Language
      *
-     * @var Language
+     * @var \SimpleSAML\Locale\Language
      */
-    private $language;
+    private Language $language;
 
     /**
      * Language code representing the current Language
      *
      * @var string
      */
-    private $langcode;
+    private string $langcode;
 
 
     /**
@@ -86,7 +86,7 @@ class Localization
      *
      * @var string
      */
-    public $i18nBackend;
+    public string $i18nBackend;
 
 
     /**
diff --git a/lib/SimpleSAML/Locale/Translate.php b/lib/SimpleSAML/Locale/Translate.php
index 75ce2a1fcce98e19c421dac1ecfb383251371138..be9ac59ed704537a8c8f46956df4476644824879 100644
--- a/lib/SimpleSAML/Locale/Translate.php
+++ b/lib/SimpleSAML/Locale/Translate.php
@@ -23,35 +23,35 @@ class Translate
      *
      * @var \SimpleSAML\Configuration
      */
-    private $configuration;
+    private Configuration $configuration;
 
     /**
      * Associative array of languages.
      *
      * @var array
      */
-    private $langtext = [];
+    private array $langtext = [];
 
     /**
      * Associative array of dictionaries.
      *
      * @var array
      */
-    private $dictionaries = [];
+    private array $dictionaries = [];
 
     /**
      * The default dictionary.
      *
      * @var string|null
      */
-    private $defaultDictionary = null;
+    private ?string $defaultDictionary = null;
 
     /**
      * The language object we'll use internally.
      *
      * @var \SimpleSAML\Locale\Language
      */
-    private $language;
+    private Language $language;
 
 
     /**
@@ -324,6 +324,7 @@ class Translate
 
         $lang = null;
         include($phpFile);
+        /** @psalm-var array|null $lang */
         if (isset($lang)) {
             return $lang;
         }
diff --git a/lib/SimpleSAML/Logger.php b/lib/SimpleSAML/Logger.php
index ec47b8a4b447738854f2b4e165af99a90b81f967..49a390dcae82555538ce599e3db878457750a83f 100644
--- a/lib/SimpleSAML/Logger.php
+++ b/lib/SimpleSAML/Logger.php
@@ -22,34 +22,34 @@ class Logger
     /**
      * @var \SimpleSAML\Logger\LoggingHandlerInterface
      */
-    private static $loggingHandler;
+    private static LoggingHandlerInterface $loggingHandler;
 
     /**
      * @var bool
      */
-    private static $initializing = false;
+    private static bool $initializing = false;
 
     /**
      * @var integer|null
      */
-    private static $logLevel = null;
+    private static ?int $logLevel = null;
 
     /**
      * @var boolean
      */
-    private static $captureLog = false;
+    private static bool $captureLog = false;
 
     /**
-     * @var array
+     * @var string[]
      */
-    private static $capturedLog = [];
+    private static array $capturedLog = [];
 
     /**
      * Array with messages logged before the logging handler was initialized.
      *
      * @var array
      */
-    private static $earlyLog = [];
+    private static array $earlyLog = [];
 
     /**
      * List of log levels.
@@ -58,7 +58,7 @@ class Logger
      *
      * @var array
      */
-    private static $logLevelStack = [];
+    private static array $logLevelStack = [];
 
     /**
      * The current mask of log levels disabled.
@@ -67,7 +67,7 @@ class Logger
      *
      * @var int
      */
-    private static $logMask = 0;
+    private static int $logMask = 0;
 
     /**
      * This constant defines the string we set the track ID to while we are fetching the track ID from the session
@@ -83,7 +83,7 @@ class Logger
      *
      * @var string
      */
-    private static $trackid = self::NO_TRACKID;
+    private static string $trackid = self::NO_TRACKID;
 
     /**
      * This variable holds the format used to log any message. Its use varies depending on the log handler used (for
@@ -113,21 +113,21 @@ class Logger
      *
      * @var string The format of the log line.
      */
-    private static $format = '%date{%b %d %H:%M:%S} %process %level %stat[%trackid] %msg';
+    private static string $format = '%date{%b %d %H:%M:%S} %process %level %stat[%trackid] %msg';
 
     /**
      * This variable tells if we have a shutdown function registered or not.
      *
      * @var bool
      */
-    private static $shutdownRegistered = false;
+    private static bool $shutdownRegistered = false;
 
     /**
      * This variable tells if we are shutting down.
      *
      * @var bool
      */
-    private static $shuttingDown = false;
+    private static bool $shuttingDown = false;
 
     /** @var int */
     public const EMERG = 0;
diff --git a/lib/SimpleSAML/Logger/ErrorLogLoggingHandler.php b/lib/SimpleSAML/Logger/ErrorLogLoggingHandler.php
index 1900893aa9874a89b3ff7b697d5c8a0ed085a5e4..e5c0cefa52af32c3bf5e33dc89d509092ca9b177 100644
--- a/lib/SimpleSAML/Logger/ErrorLogLoggingHandler.php
+++ b/lib/SimpleSAML/Logger/ErrorLogLoggingHandler.php
@@ -17,9 +17,9 @@ class ErrorLogLoggingHandler implements LoggingHandlerInterface
     /**
      * This array contains the mappings from syslog log level to names.
      *
-     * @var array
+     * @var array<int, string>
      */
-    private static $levelNames = [
+    private static array $levelNames = [
         Logger::EMERG   => 'EMERG',
         Logger::ALERT   => 'ALERT',
         Logger::CRIT    => 'CRIT',
@@ -35,7 +35,7 @@ class ErrorLogLoggingHandler implements LoggingHandlerInterface
      *
      * @var string
      */
-    private $processname;
+    private string $processname;
 
 
     /**
@@ -45,7 +45,8 @@ class ErrorLogLoggingHandler implements LoggingHandlerInterface
      */
     public function __construct(Configuration $config)
     {
-        $this->processname = $config->getString('logging.processname', 'SimpleSAMLphp');
+        // Remove any non-printable characters before storing
+        $this->processname = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $config->getString('logging.processname', 'SimpleSAMLphp'));
     }
 
 
diff --git a/lib/SimpleSAML/Logger/FileLoggingHandler.php b/lib/SimpleSAML/Logger/FileLoggingHandler.php
index f54e76ae10f89d881c422a06aeb4f8727b2f9a83..ca2c87bcdfaa9543b3c5545ee63ad7d754d75cf0 100644
--- a/lib/SimpleSAML/Logger/FileLoggingHandler.php
+++ b/lib/SimpleSAML/Logger/FileLoggingHandler.php
@@ -20,13 +20,13 @@ class FileLoggingHandler implements LoggingHandlerInterface
      *
      * @var null|string
      */
-    protected $logFile = null;
+    protected ?string $logFile = null;
 
     /**
      * This array contains the mappings from syslog log levels to names. Copied more or less directly from
      * SimpleSAML\Logger\ErrorLogLoggingHandler.
      *
-     * @var array
+     * @var array<int, string>
      */
     private static $levelNames = [
         Logger::EMERG   => 'EMERGENCY',
@@ -39,11 +39,11 @@ class FileLoggingHandler implements LoggingHandlerInterface
         Logger::DEBUG   => 'DEBUG',
     ];
 
-    /** @var string|null */
-    protected $processname = null;
+    /** @var string */
+    protected string $processname;
 
     /** @var string */
-    protected $format = "%b %d %H:%M:%S";
+    protected string $format = "%b %d %H:%M:%S";
 
 
     /**
@@ -55,7 +55,9 @@ class FileLoggingHandler implements LoggingHandlerInterface
         // get the metadata handler option from the configuration
         $this->logFile = $config->getPathValue('loggingdir', 'log/') .
             $config->getString('logging.logfile', 'simplesamlphp.log');
-        $this->processname = $config->getString('logging.processname', 'SimpleSAMLphp');
+
+        // Remove any non-printable characters before storing
+        $this->processname = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $config->getString('logging.processname', 'SimpleSAMLphp'));
 
         if (@file_exists($this->logFile)) {
             if (!@is_writeable($this->logFile)) {
diff --git a/lib/SimpleSAML/Logger/StandardErrorLoggingHandler.php b/lib/SimpleSAML/Logger/StandardErrorLoggingHandler.php
index c6860a2a22d51f7ca0539c21633b7c02fe4e82cc..e2a8f93a06df1dccc2f7514ab38ec79ff5c44075 100644
--- a/lib/SimpleSAML/Logger/StandardErrorLoggingHandler.php
+++ b/lib/SimpleSAML/Logger/StandardErrorLoggingHandler.php
@@ -22,7 +22,8 @@ class StandardErrorLoggingHandler extends FileLoggingHandler
      */
     public function __construct(Configuration $config)
     {
-        $this->processname = $config->getString('logging.processname', 'SimpleSAMLphp');
+        // Remove any non-printable characters before storing
+        $this->processname = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $config->getString('logging.processname', 'SimpleSAMLphp'));
         $this->logFile = 'php://stderr';
     }
 }
diff --git a/lib/SimpleSAML/Logger/SyslogLoggingHandler.php b/lib/SimpleSAML/Logger/SyslogLoggingHandler.php
index bb38492013e6d458f0fb8cebefa56399c737aeb5..7cf2fc6d05b022bc39547069e7a1888cdae4edad 100644
--- a/lib/SimpleSAML/Logger/SyslogLoggingHandler.php
+++ b/lib/SimpleSAML/Logger/SyslogLoggingHandler.php
@@ -15,10 +15,10 @@ use SimpleSAML\Utils;
 class SyslogLoggingHandler implements LoggingHandlerInterface
 {
     /** @var bool */
-    private $isWindows = false;
+    private bool $isWindows = false;
 
     /** @var string */
-    protected $format = "%b %d %H:%M:%S";
+    protected string $format = "%b %d %H:%M:%S";
 
 
     /**
@@ -29,7 +29,8 @@ class SyslogLoggingHandler implements LoggingHandlerInterface
     {
         $facility = $config->getInteger('logging.facility', defined('LOG_LOCAL5') ? constant('LOG_LOCAL5') : LOG_USER);
 
-        $processname = $config->getString('logging.processname', 'SimpleSAMLphp');
+        // Remove any non-printable characters before storing
+        $processname = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $config->getString('logging.processname', 'SimpleSAMLphp'));
 
         // Setting facility to LOG_USER (only valid in Windows), enable log level rewrite on windows systems
         if (Utils\System::getOS() === Utils\System::WINDOWS) {
diff --git a/lib/SimpleSAML/Memcache.php b/lib/SimpleSAML/Memcache.php
index 39e4b8a8883cfd1a6bef8a013de2dbe919dd0800..156e0bafc1a2636806d78f6e3557bfe760a9b43b 100644
--- a/lib/SimpleSAML/Memcache.php
+++ b/lib/SimpleSAML/Memcache.php
@@ -27,9 +27,9 @@ class Memcache
     /**
      * Cache of the memcache servers we are using.
      *
-     * @var \Memcached[]|null
+     * @var \Memcached[]
      */
-    private static $serverGroups = null;
+    private static array $serverGroups = [];
 
 
     /**
@@ -317,7 +317,7 @@ class Memcache
     private static function getMemcacheServers(): array
     {
         // check if we have loaded the servers already
-        if (self::$serverGroups != null) {
+        if (!empty(self::$serverGroups)) {
             return self::$serverGroups;
         }
 
diff --git a/lib/SimpleSAML/Metadata/MetaDataStorageHandler.php b/lib/SimpleSAML/Metadata/MetaDataStorageHandler.php
index 86d9446264c4b24227ba1d34b979bbb1b4173cb1..2af578cd8655dd07f7cf868ef3e270d8a6be5567 100644
--- a/lib/SimpleSAML/Metadata/MetaDataStorageHandler.php
+++ b/lib/SimpleSAML/Metadata/MetaDataStorageHandler.php
@@ -27,18 +27,18 @@ class MetaDataStorageHandler implements ClearableState
      * instance of the metadata handler. This variable will be null if
      * we haven't instantiated a metadata handler yet.
      *
-     * @var MetaDataStorageHandler|null
+     * @var \SimpleSAML\Metadata\MetaDataStorageHandler|null
      */
-    private static $metadataHandler = null;
+    private static ?MetadataStorageHandler $metadataHandler = null;
 
 
     /**
      * This is a list of all the metadata sources we have in our metadata
      * chain. When we need metadata, we will look through this chain from start to end.
      *
-     * @var MetaDataStorageSource[]
+     * @var \SimpleSAML\Metadata\MetaDataStorageSource[]
      */
-    private $sources;
+    private array $sources = [];
 
 
     /**
diff --git a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
index f40fa54002b529ea467ed318c83604e1066c6a50..3f6e9c5090ec78fffcc7ce930d765e0dcff0ebf2 100644
--- a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
+++ b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
@@ -23,7 +23,7 @@ class MetaDataStorageHandlerFlatFile extends MetaDataStorageSource
      *
      * @var string
      */
-    private $directory = '/';
+    private string $directory = '/';
 
 
     /**
@@ -31,7 +31,7 @@ class MetaDataStorageHandlerFlatFile extends MetaDataStorageSource
      *
      * @var array
      */
-    private $cachedMetadata = [];
+    private array $cachedMetadata = [];
 
 
     /**
diff --git a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerPdo.php b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerPdo.php
index 8136c7aeab088b034030500ee2b9fcecd523611e..f662f5138e5caa39054f7eae0e4f3ebee99f5057 100644
--- a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerPdo.php
+++ b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerPdo.php
@@ -22,23 +22,25 @@ class MetaDataStorageHandlerPdo extends MetaDataStorageSource
 {
     /**
      * The PDO object
+     * @var \SimpleSAML\Database
      */
-    private $db;
+    private Database $db;
 
     /**
      * Prefix to apply to the metadata table
      */
-    private $tablePrefix;
+    private string $tablePrefix = '';
 
     /**
      * This is an associative array which stores the different metadata sets we have loaded.
      */
-    private $cachedMetadata = [];
+    private array $cachedMetadata = [];
 
     /**
      * All the metadata sets supported by this MetaDataStorageHandler
+     * @var string[]
      */
-    public $supportedSets = [
+    public array $supportedSets = [
         'adfs-idp-hosted',
         'adfs-sp-remote',
         'saml20-idp-hosted',
diff --git a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerSerialize.php b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerSerialize.php
index 6e1770f3e2b097121afd466d7ef8b93e48d36b11..358ba5839e32efd4e089247e05450c3772ef9b30 100644
--- a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerSerialize.php
+++ b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerSerialize.php
@@ -30,7 +30,7 @@ class MetaDataStorageHandlerSerialize extends MetaDataStorageSource
      *
      * @var string
      */
-    private $directory = '/';
+    private string $directory = '/';
 
 
     /**
diff --git a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerXML.php b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerXML.php
index 8ce1a288ba7a3cd1cf0dba7e24e6dae2a3e9899d..8f7dba1fa8bf6d9475842f6fbf328e7ea71e69fe 100644
--- a/lib/SimpleSAML/Metadata/MetaDataStorageHandlerXML.php
+++ b/lib/SimpleSAML/Metadata/MetaDataStorageHandlerXML.php
@@ -20,7 +20,7 @@ class MetaDataStorageHandlerXML extends MetaDataStorageSource
      *
      * @var array
      */
-    private $metadata;
+    private array $metadata;
 
 
     /**
diff --git a/lib/SimpleSAML/Metadata/SAMLBuilder.php b/lib/SimpleSAML/Metadata/SAMLBuilder.php
index 2d83d5f1c4afda3a2e0a549c1a1bdd51300e37da..c6155407b78a6bae1268039acdca52fb44199148 100644
--- a/lib/SimpleSAML/Metadata/SAMLBuilder.php
+++ b/lib/SimpleSAML/Metadata/SAMLBuilder.php
@@ -46,7 +46,7 @@ class SAMLBuilder
      *
      * @var \SAML2\XML\md\EntityDescriptor
      */
-    private $entityDescriptor;
+    private EntityDescriptor $entityDescriptor;
 
 
     /**
@@ -54,7 +54,7 @@ class SAMLBuilder
      *
      * @var int|null
      */
-    private $maxCache = null;
+    private ?int $maxCache = null;
 
 
     /**
@@ -62,7 +62,7 @@ class SAMLBuilder
      *
      * @var int|null
      */
-    private $maxDuration = null;
+    private ?int $maxDuration = null;
 
 
     /**
diff --git a/lib/SimpleSAML/Metadata/SAMLParser.php b/lib/SimpleSAML/Metadata/SAMLParser.php
index 1d0a516d3e37a2a218d282784b52737847fb708a..41481d538da0c208b493027afcfb01f60306bb74 100644
--- a/lib/SimpleSAML/Metadata/SAMLParser.php
+++ b/lib/SimpleSAML/Metadata/SAMLParser.php
@@ -58,7 +58,7 @@ class SAMLParser
      *
      * @var string[]
      */
-    private static $SAML20Protocols = [
+    private static array $SAML20Protocols = [
         Constants::NS_SAMLP,
     ];
 
@@ -67,7 +67,7 @@ class SAMLParser
      *
      * @var string
      */
-    private $entityId;
+    private string $entityId;
 
     /**
      * This is an array with the processed SPSSODescriptor elements we have found in this
@@ -77,9 +77,9 @@ class SAMLParser
      *   Each assertion consumer service is stored as an associative array with the
      *   elements that parseGenericEndpoint returns.
      *
-     * @var array[]
+     * @var array
      */
-    private $spDescriptors;
+    private array $spDescriptors;
 
     /**
      * This is an array with the processed IDPSSODescriptor elements we have found.
@@ -87,79 +87,79 @@ class SAMLParser
      * - 'SingleSignOnService': Array with the IdP's single sign on service endpoints. Each endpoint is stored
      *   as an associative array with the elements that parseGenericEndpoint returns.
      *
-     * @var array[]
+     * @var array
      */
-    private $idpDescriptors;
+    private array $idpDescriptors;
 
     /**
      * List of attribute authorities we have found.
      *
      * @var array
      */
-    private $attributeAuthorityDescriptors = [];
+    private array $attributeAuthorityDescriptors = [];
 
     /**
      * This is an associative array with the organization name for this entity. The key of
      * the associative array is the language code, while the value is a string with the
      * organization name.
      *
-     * @var string[]
+     * @var array<string, string>
      */
-    private $organizationName = [];
+    private array $organizationName = [];
 
     /**
      * This is an associative array with the organization display name for this entity. The key of
      * the associative array is the language code, while the value is a string with the
      * organization display name.
      *
-     * @var string[]
+     * @var array<string, string>
      */
-    private $organizationDisplayName = [];
+    private array $organizationDisplayName = [];
 
     /**
      * This is an associative array with the organization URI for this entity. The key of
      * the associative array is the language code, while the value is the URI.
      *
-     * @var string[]
+     * @var array<string, string>
      */
-    private $organizationURL = [];
+    private array $organizationURL = [];
 
     /**
      * This is an array of the Contact Persons of this entity.
      *
-     * @var array[]
+     * @var array
      */
-    private $contacts = [];
+    private array $contacts = [];
 
     /**
      * @var array
      */
-    private $scopes;
+    private array $scopes;
 
     /**
      * @var array
      */
-    private $entityAttributes;
+    private array $entityAttributes;
 
     /**
      * An associative array of attributes from the RegistrationInfo element.
      * @var array
      */
-    private $registrationInfo;
+    private array $registrationInfo;
 
     /**
      * This is an array of elements that may be used to validate this element.
      *
      * @var \SAML2\SignedElementHelper[]
      */
-    private $validators = [];
+    private array $validators = [];
 
     /**
      * The original EntityDescriptor element for this entity, as a base64 encoded string.
      *
      * @var string
      */
-    private $entityDescriptor;
+    private string $entityDescriptor;
 
 
     /**
diff --git a/lib/SimpleSAML/Metadata/Sources/MDQ.php b/lib/SimpleSAML/Metadata/Sources/MDQ.php
index a8ef2956f01d38784966d78738f8a3221329529f..c4ccb31f38bec4ff2fdc668e2f9f09c7624b1610 100644
--- a/lib/SimpleSAML/Metadata/Sources/MDQ.php
+++ b/lib/SimpleSAML/Metadata/Sources/MDQ.php
@@ -25,14 +25,14 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
      *
      * @var string
      */
-    private $server;
+    private string $server;
 
     /**
      * The cache directory, or null if no cache directory is configured.
      *
      * @var string|null
      */
-    private $cacheDir;
+    private ?string $cacheDir;
 
 
     /**
@@ -40,7 +40,7 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
      *
      * @var integer
      */
-    private $cacheLength;
+    private int $cacheLength;
 
 
     /**
diff --git a/lib/SimpleSAML/Module.php b/lib/SimpleSAML/Module.php
index f3f4ac03a291e80adc255d4e666d9434a83337e0..ef622231928f0f06fd34f642633748108f529175 100644
--- a/lib/SimpleSAML/Module.php
+++ b/lib/SimpleSAML/Module.php
@@ -25,18 +25,18 @@ class Module
     /**
      * Index pages: file names to attempt when accessing directories.
      *
-     * @var array
+     * @var string[]
      */
-    public static $indexFiles = ['index.php', 'index.html', 'index.htm', 'index.txt'];
+    public static array $indexFiles = ['index.php', 'index.html', 'index.htm', 'index.txt'];
 
     /**
      * MIME Types
      *
      * The key is the file extension and the value the corresponding MIME type.
      *
-     * @var array
+     * @var array<string, string>
      */
-    public static $mimeTypes = [
+    public static array $mimeTypes = [
         'bmp'   => 'image/x-ms-bmp',
         'css'   => 'text/css',
         'gif'   => 'image/gif',
@@ -62,16 +62,16 @@ class Module
     /**
      * A list containing the modules currently installed.
      *
-     * @var array
+     * @var string[]
      */
-    public static $modules = [];
+    public static array $modules = [];
 
     /**
      * A list containing the modules that are enabled by default, unless specifically disabled
      *
-     * @var array
+     * @var array<string, bool>
      */
-    public static $core_modules = [
+    public static array $core_modules = [
         'core' => true,
         'saml' => true
     ];
@@ -81,7 +81,7 @@ class Module
      *
      * @var array
      */
-    public static $module_info = [];
+    public static array $module_info = [];
 
 
     /**
@@ -422,6 +422,12 @@ class Module
             if (!class_exists($className)) {
                 throw new \Exception("Could not resolve '$id': no class named '$className'.");
             }
+        } elseif (!in_array($tmp[0], self::getModules())) {
+            // Module not installed
+            throw new \Exception('No module named \'' . $tmp[0]. '\' has been installed.');
+        } elseif (!self::isModuleEnabled($tmp[0])) {
+            // Module installed, but not enabled
+            throw new \Exception('The module \'' . $tmp[0]. '\' is not enabled.');
         } else {
             // should be a module
             // make sure empty types are handled correctly
diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php
index 7800bf5c4595143872f83d4d4975c513db79d427..438abff785d89539c23de8e2cc160b216f740c4b 100644
--- a/lib/SimpleSAML/Session.php
+++ b/lib/SimpleSAML/Session.php
@@ -7,7 +7,9 @@ namespace SimpleSAML;
 use SAML2\XML\saml\AttributeValue;
 use Serializable;
 use SimpleSAML\Assert\Assert;
+use SimpleSAML\Configuration;
 use SimpleSAML\Error;
+use SimpleSAML\Session;
 use SimpleSAML\Utils;
 
 /**
@@ -41,7 +43,7 @@ class Session implements Serializable, Utils\ClearableState
      *
      * @var array
      */
-    private static $sessions = [];
+    private static array $sessions = [];
 
     /**
      * This variable holds the instance of the session - Singleton approach.
@@ -50,28 +52,28 @@ class Session implements Serializable, Utils\ClearableState
      *
      * @var \SimpleSAML\Session|null
      */
-    private static $instance = null;
+    private static ?Session $instance = null;
 
     /**
      * The global configuration.
      *
-     * @var \SimpleSAML\Configuration
+     * @var \SimpleSAML\Configuration|null
      */
-    private static $config;
+    private static ?Configuration $config;
 
     /**
      * The session ID of this session.
      *
      * @var string|null
      */
-    private $sessionId;
+    private ?string $sessionId = null;
 
     /**
      * Transient session flag.
      *
      * @var boolean|false
      */
-    private $transient = false;
+    private bool $transient = false;
 
     /**
      * The track id is a new random unique identifier that is generated for each session.
@@ -80,12 +82,12 @@ class Session implements Serializable, Utils\ClearableState
      *
      * @var string
      */
-    private $trackid;
+    private string $trackid;
 
     /**
      * @var integer|null
      */
-    private $rememberMeExpire = null;
+    private ?int $rememberMeExpire = null;
 
     /**
      * Marks a session as modified, and therefore needs to be saved before destroying
@@ -93,14 +95,14 @@ class Session implements Serializable, Utils\ClearableState
      *
      * @var bool
      */
-    private $dirty = false;
+    private bool $dirty = false;
 
     /**
      * Tells the session object that the save callback has been registered and there's no need to register it again.
      *
      * @var bool
      */
-    private $callback_registered = false;
+    private bool $callback_registered = false;
 
     /**
      * This is an array of objects which will expire automatically after a set time. It is used
@@ -112,7 +114,7 @@ class Session implements Serializable, Utils\ClearableState
      *
      * @var array
      */
-    private $dataStore = [];
+    private array $dataStore = [];
 
     /**
      * The list of IdP-SP associations.
@@ -122,7 +124,7 @@ class Session implements Serializable, Utils\ClearableState
      *
      * @var array
      */
-    private $associations = [];
+    private array $associations = [];
 
     /**
      * The authentication token.
@@ -131,7 +133,7 @@ class Session implements Serializable, Utils\ClearableState
      *
      * @var string|null
      */
-    private $authToken;
+    private ?string $authToken = null;
 
     /**
      * Authentication data.
@@ -140,7 +142,7 @@ class Session implements Serializable, Utils\ClearableState
      *
      * @var array  Associative array of associative arrays.
      */
-    private $authData = [];
+    private array $authData = [];
 
 
     /**
@@ -256,7 +258,8 @@ class Session implements Serializable, Utils\ClearableState
     public static function getSessionFromRequest(): Session
     {
         // check if we already have initialized the session
-        if (isset(self::$instance)) {
+        /** @psalm-suppress RedundantCondition */
+        if (self::$instance !== null) {
             return self::$instance;
         }
 
@@ -292,6 +295,8 @@ class Session implements Serializable, Utils\ClearableState
          * error message). This means we don't need to create a new session again, we can use the one that's loaded now
          * instead.
          */
+
+        /** @psalm-suppress TypeDoesNotContainType */
         if (self::$instance !== null) {
             return self::$instance;
         }
@@ -413,7 +418,8 @@ class Session implements Serializable, Utils\ClearableState
      */
     public static function useTransientSession(): void
     {
-        if (isset(self::$instance)) {
+        /** @psalm-suppress RedundantCondition */
+        if (self::$instance !== null) {
             // we already have a session, don't bother with a transient session
             return;
         }
@@ -775,7 +781,7 @@ class Session implements Serializable, Utils\ClearableState
     public function updateSessionCookies(array $params = []): void
     {
         $sessionHandler = SessionHandler::getSessionHandler();
-        $params = array_merge($sessionHandler->getCookieParams(), is_array($params) ? $params : []);
+        $params = array_merge($sessionHandler->getCookieParams(), $params);
 
         if ($this->sessionId !== null) {
             $sessionHandler->setCookie($sessionHandler->getSessionCookieName(), $this->sessionId, $params);
@@ -1151,6 +1157,6 @@ class Session implements Serializable, Utils\ClearableState
     {
         self::$config = null;
         self::$instance = null;
-        self::$sessions = null;
+        self::$sessions = [];
     }
 }
diff --git a/lib/SimpleSAML/SessionHandler.php b/lib/SimpleSAML/SessionHandler.php
index 97f4212f5b1c2cd275397ae6a69064c2c5b781b8..1a234ed4ed4eab0b2473a6deacfddf3c8be0bc6a 100644
--- a/lib/SimpleSAML/SessionHandler.php
+++ b/lib/SimpleSAML/SessionHandler.php
@@ -22,9 +22,9 @@ abstract class SessionHandler
      * instance of the session handler. This variable will be NULL if
      * we haven't instantiated a session handler yet.
      *
-     * @var \SimpleSAML\SessionHandler
+     * @var \SimpleSAML\SessionHandler|null
      */
-    protected static $sessionHandler;
+    protected static ?SessionHandler $sessionHandler = null;
 
 
     /**
diff --git a/lib/SimpleSAML/SessionHandlerCookie.php b/lib/SimpleSAML/SessionHandlerCookie.php
index cb5fbfc9d022783a9eace631047d684ce4b9de39..a8d2c868d631ddbb53b7eab6bd2429aa5c3837ef 100644
--- a/lib/SimpleSAML/SessionHandlerCookie.php
+++ b/lib/SimpleSAML/SessionHandlerCookie.php
@@ -24,7 +24,7 @@ abstract class SessionHandlerCookie extends SessionHandler
      *
      * @var string|null
      */
-    private $session_id = null;
+    private ?string $session_id = null;
 
 
     /**
@@ -32,7 +32,7 @@ abstract class SessionHandlerCookie extends SessionHandler
      *
      * @var string
      */
-    protected $cookie_name;
+    protected string $cookie_name;
 
 
     /**
diff --git a/lib/SimpleSAML/SessionHandlerPHP.php b/lib/SimpleSAML/SessionHandlerPHP.php
index 587ea15f0339a20519ee48d885d6eae89e4d3ec0..e0f2646148b9852b7e22f5be1956001319637b88 100644
--- a/lib/SimpleSAML/SessionHandlerPHP.php
+++ b/lib/SimpleSAML/SessionHandlerPHP.php
@@ -23,7 +23,7 @@ class SessionHandlerPHP extends SessionHandler
      *
      * @var string
      */
-    protected $cookie_name;
+    protected string $cookie_name;
 
     /**
      * An associative array containing the details of a session existing previously to creating or loading one with this
@@ -35,7 +35,7 @@ class SessionHandlerPHP extends SessionHandler
      *
      * @var array
      */
-    private $previous_session = [];
+    private array $previous_session = [];
 
 
     /**
@@ -48,7 +48,7 @@ class SessionHandlerPHP extends SessionHandler
         parent::__construct();
 
         $config = Configuration::getInstance();
-        $this->cookie_name = $config->getString('session.phpsession.cookiename', null);
+        $this->cookie_name = $config->getString('session.phpsession.cookiename', ini_get('session.name') ?? 'PHPSESSID');
 
         if (session_status() === PHP_SESSION_ACTIVE) {
             if (session_name() === $this->cookie_name || $this->cookie_name === null) {
diff --git a/lib/SimpleSAML/SessionHandlerStore.php b/lib/SimpleSAML/SessionHandlerStore.php
index 66c2c911bb002b7cae4b15a47adbcca8b756273a..ec7cbfe1a20b6491bc85043709a5f980abcd16f0 100644
--- a/lib/SimpleSAML/SessionHandlerStore.php
+++ b/lib/SimpleSAML/SessionHandlerStore.php
@@ -19,7 +19,7 @@ class SessionHandlerStore extends SessionHandlerCookie
      *
      * @var \SimpleSAML\Store
      */
-    private $store;
+    private Store $store;
 
 
     /**
diff --git a/lib/SimpleSAML/Stats.php b/lib/SimpleSAML/Stats.php
index 4c47c0cc937eeb6121a5a02e81b2538e48ef7963..6176cbe87500960e2fdb76860d8a191c9bfbf193 100644
--- a/lib/SimpleSAML/Stats.php
+++ b/lib/SimpleSAML/Stats.php
@@ -21,15 +21,15 @@ class Stats
      *
      * @var boolean
      */
-    private static $initialized = false;
+    private static bool $initialized = false;
 
 
     /**
      * The statistics output callbacks.
      *
-     * @var array
+     * @var \SimpleSAML\Stats\Output[]
      */
-    private static $outputs = null;
+    private static array $outputs = [];
 
 
     /**
diff --git a/lib/SimpleSAML/Store.php b/lib/SimpleSAML/Store.php
index 86e86377733c7a921d6346e477d9442bcf807289..12e856f03dfd70f0781686fbc57d35177fef5b26 100644
--- a/lib/SimpleSAML/Store.php
+++ b/lib/SimpleSAML/Store.php
@@ -21,7 +21,7 @@ abstract class Store implements Utils\ClearableState
      *
      * @var \SimpleSAML\Store|false|null
      */
-    private static $instance;
+    private static $instance = null;
 
 
     /**
diff --git a/lib/SimpleSAML/Store/Memcache.php b/lib/SimpleSAML/Store/Memcache.php
index 8592675d6d48efeb6c723542d40005e77e6158d8..230a3ca752cf7d66e35ccb0ec53f203505638fe9 100644
--- a/lib/SimpleSAML/Store/Memcache.php
+++ b/lib/SimpleSAML/Store/Memcache.php
@@ -20,7 +20,7 @@ class Memcache extends Store
      *
      * @var string
      */
-    private $prefix;
+    private string $prefix;
 
 
     /**
diff --git a/lib/SimpleSAML/Store/Redis.php b/lib/SimpleSAML/Store/Redis.php
index dbdeb1d3adcdea6b53924ffa4bbdafc1c19dbd28..6a6aec8b404640066972717b7b02009b01c5ffdb 100644
--- a/lib/SimpleSAML/Store/Redis.php
+++ b/lib/SimpleSAML/Store/Redis.php
@@ -18,7 +18,7 @@ use SimpleSAML\Store;
 class Redis extends Store
 {
     /** @var \Predis\Client */
-    public $redis;
+    public Client $redis;
 
 
     /**
@@ -31,7 +31,7 @@ class Redis extends Store
             throw new Error\CriticalConfigurationError('predis/predis is not available.');
         }
 
-        Assert::nullOrIsInstanceOf($redis, \Predis\Client::class);
+        Assert::nullOrIsInstanceOf($redis, Client::class);
 
         if ($redis === null) {
             $config = Configuration::getInstance();
diff --git a/lib/SimpleSAML/Store/SQL.php b/lib/SimpleSAML/Store/SQL.php
index 10435dcc5a4bbd1e6919cc1dcaa43b6a174dab99..e5bcd6fb51a4c9096374043dc34bff24044486b2 100644
--- a/lib/SimpleSAML/Store/SQL.php
+++ b/lib/SimpleSAML/Store/SQL.php
@@ -23,28 +23,28 @@ class SQL extends Store
      *
      * @var \PDO
      */
-    public $pdo;
+    public PDO $pdo;
 
     /**
      * Our database driver.
      *
      * @var string
      */
-    public $driver;
+    public string $driver;
 
     /**
      * The prefix we should use for our tables.
      *
      * @var string
      */
-    public $prefix;
+    public string $prefix;
 
     /**
      * Associative array of table versions.
      *
      * @var array
      */
-    private $tableVersions;
+    private array $tableVersions;
 
 
     /**
@@ -313,9 +313,6 @@ class SQL extends Store
         }
 
         $value = $row['_value'];
-//        if (is_resource($value)) {
-//            $value = stream_get_contents($value);
-//        }
 
         Assert::string($value);
 
diff --git a/lib/SimpleSAML/Utils/Config/Metadata.php b/lib/SimpleSAML/Utils/Config/Metadata.php
index e4c66ee218a0590dc8d70dbe3957f4987e88dbb9..938eacf1e6ca7a8191156dab1c85c5825a3c88e1 100644
--- a/lib/SimpleSAML/Utils/Config/Metadata.php
+++ b/lib/SimpleSAML/Utils/Config/Metadata.php
@@ -20,7 +20,7 @@ class Metadata
      *
      * @var string
      */
-    public static $ENTITY_CATEGORY = 'http://macedir.org/entity-category';
+    public static string $ENTITY_CATEGORY = 'http://macedir.org/entity-category';
 
 
     /**
@@ -28,7 +28,7 @@ class Metadata
      *
      * @var string
      */
-    public static $HIDE_FROM_DISCOVERY = 'http://refeds.org/category/hide-from-discovery';
+    public static string $HIDE_FROM_DISCOVERY = 'http://refeds.org/category/hide-from-discovery';
 
 
     /**
@@ -38,10 +38,10 @@ class Metadata
      * it is required to allow additons to the main contact person element for trust
      * frameworks.
      *
-     * @var array The valid configuration options for a contact configuration array.
+     * @var string[] The valid configuration options for a contact configuration array.
      * @see "Metadata for the OASIS Security Assertion Markup Language (SAML) V2.0", section 2.3.2.2.
      */
-    public static $VALID_CONTACT_OPTIONS = [
+    public static array $VALID_CONTACT_OPTIONS = [
         'contactType',
         'emailAddress',
         'givenName',
@@ -53,10 +53,10 @@ class Metadata
 
 
     /**
-     * @var array The valid types of contact for a contact configuration array.
+     * @var string[] The valid types of contact for a contact configuration array.
      * @see "Metadata for the OASIS Security Assertion Markup Language (SAML) V2.0", section 2.3.2.2.
      */
-    public static $VALID_CONTACT_TYPES = [
+    public static array $VALID_CONTACT_TYPES = [
         'technical',
         'support',
         'administrative',
diff --git a/lib/SimpleSAML/Utils/EMail.php b/lib/SimpleSAML/Utils/EMail.php
index 6317cd6b2bae59d6384f68b2702896a3fb5e6438..38a71ad872977d981d0aa9593cfb704ec89248c7 100644
--- a/lib/SimpleSAML/Utils/EMail.php
+++ b/lib/SimpleSAML/Utils/EMail.php
@@ -20,13 +20,13 @@ use SimpleSAML\XHTML\Template;
 class EMail
 {
     /** @var array Dictionary with multivalues */
-    private $data = [];
+    private array $data = [];
 
     /** @var string Introduction text */
-    private $text = '';
+    private string $text = '';
 
-    /** @var PHPMailer The mailer instance */
-    private $mail;
+    /** @var \PHPMailer\PHPMailer\PHPMailer The mailer instance */
+    private PHPMailer $mail;
 
 
     /**
diff --git a/lib/SimpleSAML/Utils/Time.php b/lib/SimpleSAML/Utils/Time.php
index ee860b78cc0995b002e88fcb957ac762093a422c..9540e2646fbf31104cd8a9b6e6fb54289fa65a7a 100644
--- a/lib/SimpleSAML/Utils/Time.php
+++ b/lib/SimpleSAML/Utils/Time.php
@@ -21,7 +21,7 @@ class Time
      *
      * @var bool
      */
-    private static $tz_initialized = false;
+    private static bool $tz_initialized = false;
 
 
     /**
diff --git a/lib/SimpleSAML/XHTML/IdPDisco.php b/lib/SimpleSAML/XHTML/IdPDisco.php
index c0199a445dd6ddc06b963fff7df7abcf94fcb97f..ffc7da248dd13a5927b82ac79daaf57ed0dc765c 100644
--- a/lib/SimpleSAML/XHTML/IdPDisco.php
+++ b/lib/SimpleSAML/XHTML/IdPDisco.php
@@ -28,42 +28,42 @@ class IdPDisco
      *
      * @var \SimpleSAML\Configuration
      */
-    protected $config;
+    protected Configuration $config;
 
     /**
      * The identifier of this discovery service.
      *
      * @var string
      */
-    protected $instance;
+    protected string $instance;
 
     /**
      * An instance of the metadata handler, which will allow us to fetch metadata about IdPs.
      *
      * @var \SimpleSAML\Metadata\MetaDataStorageHandler
      */
-    protected $metadata;
+    protected MetadataStorageHandler $metadata;
 
     /**
      * The users session.
      *
      * @var \SimpleSAML\Session
      */
-    protected $session;
+    protected Session $session;
 
     /**
      * The metadata sets we find allowed entities in, in prioritized order.
      *
      * @var array
      */
-    protected $metadataSets;
+    protected array $metadataSets;
 
     /**
      * The entity id of the SP which accesses this IdP discovery service.
      *
      * @var string
      */
-    protected $spEntityId;
+    protected string $spEntityId;
 
     /**
      * HTTP parameter from the request, indicating whether the discovery service
@@ -71,14 +71,14 @@ class IdPDisco
      *
      * @var boolean
      */
-    protected $isPassive;
+    protected bool $isPassive;
 
     /**
      * The SP request to set the IdPentityID...
      *
      * @var string|null
      */
-    protected $setIdPentityID = null;
+    protected ?string $setIdPentityID = null;
 
     /**
      * The name of the query parameter which should contain the users choice of IdP.
@@ -86,7 +86,7 @@ class IdPDisco
      *
      * @var string
      */
-    protected $returnIdParam;
+    protected string $returnIdParam;
 
     /**
      * The list of scoped idp's. The intersection between the metadata idpList
@@ -95,14 +95,14 @@ class IdPDisco
      *
      * @var array
      */
-    protected $scopedIDPList = [];
+    protected array $scopedIDPList = [];
 
     /**
      * The URL the user should be redirected to after choosing an IdP.
      *
      * @var string
      */
-    protected $returnURL;
+    protected string $returnURL;
 
 
     /**
diff --git a/lib/SimpleSAML/XHTML/Template.php b/lib/SimpleSAML/XHTML/Template.php
index 3fde9897bf4ca0901ad2fc0784ea2af45223f877..2326b7d29bf1cac208d1f8d134de75cdfb56b197 100644
--- a/lib/SimpleSAML/XHTML/Template.php
+++ b/lib/SimpleSAML/XHTML/Template.php
@@ -36,56 +36,56 @@ class Template extends Response
      *
      * @var array
      */
-    public $data = [];
+    public array $data = [];
 
     /**
      * A translator instance configured to work with this template.
      *
      * @var \SimpleSAML\Locale\Translate
      */
-    private $translator;
+    private Translate $translator;
 
     /**
      * The localization backend
      *
      * @var \SimpleSAML\Locale\Localization
      */
-    private $localization;
+    private Localization $localization;
 
     /**
      * The configuration to use in this template.
      *
      * @var \SimpleSAML\Configuration
      */
-    private $configuration;
+    private Configuration $configuration;
 
     /**
      * The file to load in this template.
      *
      * @var string
      */
-    private $template = 'default.php';
+    private string $template = 'default.php';
 
     /**
      * The twig environment.
      *
      * @var \Twig\Environment
      */
-    private $twig;
+    private \Twig\Environment $twig;
 
     /**
      * The template name.
      *
      * @var string
      */
-    private $twig_template;
+    private string $twig_template;
 
     /**
      * Current module, if any.
      *
-     * @var string
+     * @var string|null
      */
-    private $module;
+    private ?string $module = null;
 
     /**
      * A template controller, if any.
@@ -96,7 +96,7 @@ class Template extends Response
      *
      * @var \SimpleSAML\XHTML\TemplateControllerInterface|null
      */
-    private $controller = null;
+    private ?TemplateControllerInterface $controller = null;
 
     /**
      * Whether we are using a non-default theme or not.
@@ -107,7 +107,7 @@ class Template extends Response
      *
      * @var array
      */
-    private $theme = ['module' => null, 'name' => 'default'];
+    private array $theme = ['module' => null, 'name' => 'default'];
 
 
     /**
diff --git a/lib/SimpleSAML/XHTML/TemplateControllerInterface.php b/lib/SimpleSAML/XHTML/TemplateControllerInterface.php
index 488676cd37052c4504621bb2a91f0070bf43dffa..dbda8a6923ae551007484c354836e227037d6da5 100644
--- a/lib/SimpleSAML/XHTML/TemplateControllerInterface.php
+++ b/lib/SimpleSAML/XHTML/TemplateControllerInterface.php
@@ -13,7 +13,6 @@ use Twig\Environment;
  */
 interface TemplateControllerInterface
 {
-
     /**
      * Implement to modify the twig environment after its initialization (e.g. add filters or extensions).
      *
diff --git a/lib/SimpleSAML/XML/Errors.php b/lib/SimpleSAML/XML/Errors.php
index 155cb66465284ae1ed0a6f41b1cee25b4288fa44..ee34f8a92bfad7b187e0320cd7a96835c3d2344c 100644
--- a/lib/SimpleSAML/XML/Errors.php
+++ b/lib/SimpleSAML/XML/Errors.php
@@ -21,12 +21,12 @@ class Errors
     /**
      * @var array This is an stack of error logs. The topmost element is the one we are currently working on.
      */
-    private static $errorStack = [];
+    private static array $errorStack = [];
 
     /**
      * @var bool This is the xml error state we had before we began logging.
      */
-    private static $xmlErrorState;
+    private static bool $xmlErrorState;
 
 
     /**
diff --git a/lib/SimpleSAML/XML/Parser.php b/lib/SimpleSAML/XML/Parser.php
index 07f506e172ae28b10f6f12169c29dbc2d3cbb9f1..ba2c4e13d27b50a1e5fca83a2b89221886e94ca5 100644
--- a/lib/SimpleSAML/XML/Parser.php
+++ b/lib/SimpleSAML/XML/Parser.php
@@ -15,7 +15,7 @@ use SimpleXMLElement;
 class Parser
 {
     /** @var \SimpleXMLElement */
-    public $simplexml;
+    public SimpleXMLElement $simplexml;
 
     /**
      * @param string $xml
diff --git a/lib/SimpleSAML/XML/Signer.php b/lib/SimpleSAML/XML/Signer.php
index 769b8dd76d2555f59d18cd36ad7dfc3553555720..898eb639a120ef205967df5c9b76e121fbf32264 100644
--- a/lib/SimpleSAML/XML/Signer.php
+++ b/lib/SimpleSAML/XML/Signer.php
@@ -25,23 +25,23 @@ class Signer
     /**
      * @var string The name of the ID attribute.
      */
-    private $idAttrName = '';
+    private string $idAttrName = '';
 
     /**
-     * @var XMLSecurityKey|false  The private key (as an XMLSecurityKey).
+     * @var \RobRichards\XMLSecLibs\XMLSecurityKey|false  The private key (as an XMLSecurityKey).
      */
     private $privateKey = false;
 
     /**
      * @var string The certificate (as text).
      */
-    private $certificate = '';
+    private string $certificate = '';
 
 
     /**
      * @var array Extra certificates which should be included in the response.
      */
-    private $extraCertificates = [];
+    private array $extraCertificates = [];
 
 
     /**
diff --git a/lib/SimpleSAML/XML/Validator.php b/lib/SimpleSAML/XML/Validator.php
index e09332bdb1648da89d10236766a342687b3072fd..7648910ede75b9f203c96036bfc7a3a59e8e69e8 100644
--- a/lib/SimpleSAML/XML/Validator.php
+++ b/lib/SimpleSAML/XML/Validator.php
@@ -23,12 +23,12 @@ class Validator
      * @var string|null This variable contains the X509 certificate the XML document
      *             was signed with, or NULL if it wasn't signed with an X509 certificate.
      */
-    private $x509Certificate = null;
+    private ?string $x509Certificate = null;
 
     /**
      * @var array|null This variable contains the nodes which are signed.
      */
-    private $validNodes = null;
+    private ?array $validNodes = null;
 
 
     /**
diff --git a/modules/admin/lib/Controller/Config.php b/modules/admin/lib/Controller/Config.php
index 463e266230e3d63ad052b9679942d3f99f53fbcf..e4823002060e6e5eb08a058654d0ddecf8edce07 100644
--- a/modules/admin/lib/Controller/Config.php
+++ b/modules/admin/lib/Controller/Config.php
@@ -27,7 +27,7 @@ class Config
     public const RELEASES_API = 'https://api.github.com/repos/simplesamlphp/simplesamlphp/releases/latest';
 
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /**
      * @var \SimpleSAML\Utils\Auth|string
@@ -35,11 +35,11 @@ class Config
      */
     protected $authUtils = Utils\Auth::class;
 
-    /** @var Menu */
-    protected $menu;
+    /** @var \SimpleSAML\Module\admin\Controller\Menu */
+    protected Menu $menu;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
@@ -137,6 +137,7 @@ class Config
 
         Module::callHooks('configpage', $t);
         $this->menu->addOption('logout', Utils\Auth::getAdminLogoutURL(), Translate::noop('Log out'));
+        /** @psalm-var \SimpleSAML\XHTML\Template $t */
         return $this->menu->insert($t);
     }
 
diff --git a/modules/admin/lib/Controller/Federation.php b/modules/admin/lib/Controller/Federation.php
index d4ff475de74fa6944546c879a053de8c81f4ea0e..2b349d877c895026faf3b0b3ca870e661bb23880 100644
--- a/modules/admin/lib/Controller/Federation.php
+++ b/modules/admin/lib/Controller/Federation.php
@@ -34,7 +34,7 @@ use Symfony\Component\VarExporter\VarExporter;
 class Federation
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /**
      * @var \SimpleSAML\Auth\Source|string
@@ -49,10 +49,10 @@ class Federation
     protected $authUtils = Utils\Auth::class;
 
     /** @var \SimpleSAML\Metadata\MetaDataStorageHandler */
-    protected $mdHandler;
+    protected MetadataStorageHandler $mdHandler;
 
-    /** @var Menu */
-    protected $menu;
+    /** @var \SimpleSAML\Module\admin\Controller\Menu */
+    protected Menu $menu;
 
 
     /**
@@ -195,6 +195,7 @@ class Federation
         Assert::isInstanceOf($t, Template::class);
 
         $this->menu->addOption('logout', $t->data['logouturl'], Translate::noop('Log out'));
+        /** @psalm-var \SimpleSAML\XHTML\Template $t */
         return $this->menu->insert($t);
     }
 
diff --git a/modules/admin/lib/Controller/Menu.php b/modules/admin/lib/Controller/Menu.php
index 1754042f8c19fdfcfe2458d8ffcfafc2123b7cbd..7e6345f11bd48205dbcde03e0597a99287b7650d 100644
--- a/modules/admin/lib/Controller/Menu.php
+++ b/modules/admin/lib/Controller/Menu.php
@@ -17,7 +17,7 @@ use SimpleSAML\XHTML\Template;
 final class Menu
 {
     /** @var array */
-    private $options;
+    private array $options;
 
 
     /**
@@ -88,7 +88,10 @@ final class Menu
     {
         $template->data['menu'] = $this->options;
         Module::callHooks('adminmenu', $template);
+
         Assert::isInstanceOf($template, Template::class);
+
+        /** @psalm-var \SimpleSAML\XHTML\Template $template */
         return $template;
     }
 }
diff --git a/modules/admin/lib/Controller/Test.php b/modules/admin/lib/Controller/Test.php
index 5d23f41eb197e488e6ac10d9f982df811e1b7f12..3be69e3d967213458d6e496681cfd47c3046e2d0 100644
--- a/modules/admin/lib/Controller/Test.php
+++ b/modules/admin/lib/Controller/Test.php
@@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Response;
 class Test
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /**
      * @var \SimpleSAML\Utils\Auth|string
@@ -48,11 +48,11 @@ class Test
      */
     protected $authState = Auth\State::class;
 
-    /** @var Menu */
-    protected $menu;
+    /** @var \SimpleSAML\Module\admin\Controller\Menu */
+    protected Menu $menu;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
@@ -118,8 +118,9 @@ class Test
                 'sources' => Auth\Source::getSources(),
             ];
         } else {
-            $simple = $this->authSimple;
-            $authsource = new $simple($as);
+            /** @psalm-suppress UndefinedClass */
+            $authsource = new $this->authSimple($as);
+
             if (!is_null($request->query->get('logout'))) {
                 return new RunnableResponse([$authsource, 'logout'], [$this->config->getBasePath() . 'logout.php']);
             } elseif (!is_null($request->query->get(Auth\State::EXCEPTION_PARAM))) {
@@ -161,6 +162,7 @@ class Test
         Assert::isInstanceOf($t, Template::class);
 
         $this->menu->addOption('logout', Utils\Auth::getAdminLogoutURL(), Translate::noop('Log out'));
+        /** @var \SimpleSAML\XHTML\Template $t */
         return $this->menu->insert($t);
     }
 
diff --git a/modules/core/lib/Auth/Process/AttributeAdd.php b/modules/core/lib/Auth/Process/AttributeAdd.php
index 28c82fc1aa53a917cced97fc4fd589b857d8a09b..d30084a8738a59201f39f8c7e14d9d92b0ccab9a 100644
--- a/modules/core/lib/Auth/Process/AttributeAdd.php
+++ b/modules/core/lib/Auth/Process/AttributeAdd.php
@@ -21,7 +21,7 @@ class AttributeAdd extends Auth\ProcessingFilter
      * Flag which indicates wheter this filter should append new values or replace old values.
      * @var bool
      */
-    private $replace = false;
+    private bool $replace = false;
 
     /**
      * Attributes which should be added/appended.
@@ -29,7 +29,7 @@ class AttributeAdd extends Auth\ProcessingFilter
      * Associative array of arrays.
      * @var array
      */
-    private $attributes = [];
+    private array $attributes = [];
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/AttributeAlter.php b/modules/core/lib/Auth/Process/AttributeAlter.php
index badf28ad3d09e3ab50554dd3e430cfd2f17e0833..29a2c0823aa7aae0041d2c46217cf20168875147 100644
--- a/modules/core/lib/Auth/Process/AttributeAlter.php
+++ b/modules/core/lib/Auth/Process/AttributeAlter.php
@@ -21,19 +21,19 @@ class AttributeAlter extends Auth\ProcessingFilter
      * Should the pattern found be replaced?
      * @var bool
      */
-    private $replace = false;
+    private bool $replace = false;
 
     /**
      * Should the value found be removed?
      * @var bool
      */
-    private $remove = false;
+    private bool $remove = false;
 
     /**
      * Pattern to search for.
      * @var string
      */
-    private $pattern = '';
+    private string $pattern = '';
 
     /**
      * String to replace the pattern found with.
@@ -45,13 +45,13 @@ class AttributeAlter extends Auth\ProcessingFilter
      * Attribute to search in
      * @var string
      */
-    private $subject = '';
+    private string $subject = '';
 
     /**
      * Attribute to place the result in.
      * @var string
      */
-    private $target = '';
+    private string $target = '';
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/AttributeCopy.php b/modules/core/lib/Auth/Process/AttributeCopy.php
index d0767528cd2857902af25c998d8284ad92681e07..199e4a8a24464f419878d27891bd638f4544a0eb 100644
--- a/modules/core/lib/Auth/Process/AttributeCopy.php
+++ b/modules/core/lib/Auth/Process/AttributeCopy.php
@@ -28,7 +28,7 @@ class AttributeCopy extends Auth\ProcessingFilter
      * Assosiative array with the mappings of attribute names.
      * @var array
      */
-    private $map = [];
+    private array $map = [];
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/AttributeLimit.php b/modules/core/lib/Auth/Process/AttributeLimit.php
index 91d32fc3a40eda55db50252578ed211c1e1555ee..490940f3084293df10e530658373634bac353679 100644
--- a/modules/core/lib/Auth/Process/AttributeLimit.php
+++ b/modules/core/lib/Auth/Process/AttributeLimit.php
@@ -20,14 +20,14 @@ class AttributeLimit extends Auth\ProcessingFilter
      * List of attributes which this filter will allow through.
      * @var array
      */
-    private $allowedAttributes = [];
+    private array $allowedAttributes = [];
 
     /**
      * Whether the 'attributes' option in the metadata takes precedence.
      *
      * @var bool
      */
-    private $isDefault = false;
+    private bool $isDefault = false;
 
 
     /**
@@ -50,14 +50,12 @@ class AttributeLimit extends Auth\ProcessingFilter
                         var_export($value, true));
                 }
                 $this->allowedAttributes[] = $value;
-            } elseif (is_string($index)) {
+            } else { // Can only be string since PHP only allows string|int for array keys
                 if (!is_array($value)) {
                     throw new Error\Exception('AttributeLimit: Values for ' .
                         var_export($index, true) . ' must be specified in an array.');
                 }
                 $this->allowedAttributes[$index] = $value;
-            } else {
-                throw new Error\Exception('AttributeLimit: Invalid option: ' . var_export($index, true));
             }
         }
     }
diff --git a/modules/core/lib/Auth/Process/AttributeMap.php b/modules/core/lib/Auth/Process/AttributeMap.php
index d96068c9d25394729905e0b913a7440c74c56775..3fd36bdae63c4c997d8df4d17133569052e6bccc 100644
--- a/modules/core/lib/Auth/Process/AttributeMap.php
+++ b/modules/core/lib/Auth/Process/AttributeMap.php
@@ -21,13 +21,13 @@ class AttributeMap extends Auth\ProcessingFilter
      * Associative array with the mappings of attribute names.
      * @var array
      */
-    private $map = [];
+    private array $map = [];
 
     /**
      * Should attributes be duplicated or renamed.
      * @var bool
      */
-    private $duplicate = false;
+    private bool $duplicate = false;
 
 
     /**
@@ -55,10 +55,6 @@ class AttributeMap extends Auth\ProcessingFilter
                 continue;
             }
 
-            if (!is_string($origName)) {
-                throw new Exception('Invalid attribute name: ' . var_export($origName, true));
-            }
-
             if (!is_string($newName) && !is_array($newName)) {
                 throw new Exception('Invalid attribute name: ' . var_export($newName, true));
             }
diff --git a/modules/core/lib/Auth/Process/AttributeValueMap.php b/modules/core/lib/Auth/Process/AttributeValueMap.php
index 8f52114e4e396eb84c892ac7ebcbf553dd838a0f..26636d35bb4d020a40d1c76d9bc0a77e912370dd 100644
--- a/modules/core/lib/Auth/Process/AttributeValueMap.php
+++ b/modules/core/lib/Auth/Process/AttributeValueMap.php
@@ -20,31 +20,31 @@ class AttributeValueMap extends Auth\ProcessingFilter
      * The name of the attribute we should assign values to (ie: the target attribute).
      * @var string
      */
-    private $targetattribute = '';
+    private string $targetattribute = '';
 
     /**
      * The name of the attribute we should create values from.
      * @var string
      */
-    private $sourceattribute = '';
+    private string $sourceattribute = '';
 
     /**
      * The required $sourceattribute values and target affiliations.
      * @var array
      */
-    private $values = [];
+    private array $values = [];
 
     /**
      * Whether $sourceattribute should be kept or not.
      * @var bool
      */
-    private $keep = false;
+    private bool $keep = false;
 
     /**
      * Whether $target attribute values should be replaced by new values or not.
      * @var bool
      */
-    private $replace = false;
+    private bool $replace = false;
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/Cardinality.php b/modules/core/lib/Auth/Process/Cardinality.php
index a05e67fd1c533fed4b8a0c416e7c7f9e6562ebae..5ad50c127f25336151b6e7f85ac5b6381422c84c 100644
--- a/modules/core/lib/Auth/Process/Cardinality.php
+++ b/modules/core/lib/Auth/Process/Cardinality.php
@@ -19,13 +19,13 @@ use SimpleSAML\Utils;
 class Cardinality extends Auth\ProcessingFilter
 {
     /** @var array Associative array with the mappings of attribute names. */
-    private $cardinality = [];
+    private array $cardinality = [];
 
     /** @var array Entities that should be ignored */
-    private $ignoreEntities = [];
+    private array $ignoreEntities = [];
 
     /** @var \SimpleSAML\Utils\HttpAdapter */
-    private $http;
+    private Utils\HttpAdapter $http;
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/CardinalitySingle.php b/modules/core/lib/Auth/Process/CardinalitySingle.php
index 0593c2d344db5a5a7499920b1d9896c692510964..c849e7c8b596ea63d1052fa3e57de5237b335c41 100644
--- a/modules/core/lib/Auth/Process/CardinalitySingle.php
+++ b/modules/core/lib/Auth/Process/CardinalitySingle.php
@@ -21,22 +21,22 @@ use SimpleSAML\Utils;
 class CardinalitySingle extends Auth\ProcessingFilter
 {
     /** @var array Attributes that should be single-valued or we generate an error */
-    private $singleValued = [];
+    private array $singleValued = [];
 
     /** @var array Attributes for which the first value should be taken */
-    private $firstValue = [];
+    private array $firstValue = [];
 
     /** @var array Attributes that can be flattened to a single value */
-    private $flatten = [];
+    private array $flatten = [];
 
     /** @var string Separator for flattened value */
-    private $flattenWith = ';';
+    private string $flattenWith = ';';
 
     /** @var array Entities that should be ignored */
-    private $ignoreEntities = [];
+    private array $ignoreEntities = [];
 
     /** @var \SimpleSAML\Utils\HttpAdapter */
-    private $http;
+    private Utils\HttpAdapter $http;
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/GenerateGroups.php b/modules/core/lib/Auth/Process/GenerateGroups.php
index 5793381f23b6116e1ce1356cf902bd57e6e776e3..2a8eadef7a1930a5e7e180ddfbd60e7954983aea 100644
--- a/modules/core/lib/Auth/Process/GenerateGroups.php
+++ b/modules/core/lib/Auth/Process/GenerateGroups.php
@@ -20,7 +20,7 @@ class GenerateGroups extends Auth\ProcessingFilter
      * The attributes we should generate groups from.
      * @var array
      */
-    private $generateGroupsFrom;
+    private array $generateGroupsFrom;
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/LanguageAdaptor.php b/modules/core/lib/Auth/Process/LanguageAdaptor.php
index c6d14c9f0d174589d4a62e76b18b7618c4256cd2..c621172e6f61129548a03c457c34b3618b2c236d 100644
--- a/modules/core/lib/Auth/Process/LanguageAdaptor.php
+++ b/modules/core/lib/Auth/Process/LanguageAdaptor.php
@@ -17,7 +17,7 @@ use SimpleSAML\Logger;
 class LanguageAdaptor extends Auth\ProcessingFilter
 {
     /** @var string */
-    private $langattr = 'preferredLanguage';
+    private string $langattr = 'preferredLanguage';
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/PHP.php b/modules/core/lib/Auth/Process/PHP.php
index 45b5b465060db8eee901ffca6b7c4df85b2aec44..15428a461a4cce69e45f34cc1704fe8c58d1df7c 100644
--- a/modules/core/lib/Auth/Process/PHP.php
+++ b/modules/core/lib/Auth/Process/PHP.php
@@ -21,7 +21,7 @@ class PHP extends Auth\ProcessingFilter
      *
      * @var string
      */
-    private $code;
+    private string $code;
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/ScopeAttribute.php b/modules/core/lib/Auth/Process/ScopeAttribute.php
index 1b6ceca7cabd7c6943810d194a349fc01ae692ce..18955f9f64fbc171c3857504f4f3cf49dca18025 100644
--- a/modules/core/lib/Auth/Process/ScopeAttribute.php
+++ b/modules/core/lib/Auth/Process/ScopeAttribute.php
@@ -21,28 +21,28 @@ class ScopeAttribute extends Auth\ProcessingFilter
      *
      * @var string
      */
-    private $scopeAttribute;
+    private string $scopeAttribute;
 
     /**
      * The attribute we want to add scope to.
      *
      * @var string
      */
-    private $sourceAttribute;
+    private string $sourceAttribute;
 
     /**
      * The attribute we want to add the scoped attributes to.
      *
      * @var string
      */
-    private $targetAttribute;
+    private string $targetAttribute;
 
     /**
      * Only modify targetAttribute if it doesn't already exist.
      *
      * @var bool
      */
-    private $onlyIfEmpty = false;
+    private bool $onlyIfEmpty = false;
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/ScopeFromAttribute.php b/modules/core/lib/Auth/Process/ScopeFromAttribute.php
index 121c6e3f3ee5af6f48209c2c03729f6d6407ed59..7734cacb42b2ba35107cb8aff953e2dbe86ec710 100644
--- a/modules/core/lib/Auth/Process/ScopeFromAttribute.php
+++ b/modules/core/lib/Auth/Process/ScopeFromAttribute.php
@@ -32,14 +32,14 @@ class ScopeFromAttribute extends Auth\ProcessingFilter
      *
      * @var string
      */
-    private $sourceAttribute;
+    private string $sourceAttribute;
 
     /**
      * The name of the attribute which includes the scope
      *
      * @var string
      */
-    private $targetAttribute;
+    private string $targetAttribute;
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/StatisticsWithAttribute.php b/modules/core/lib/Auth/Process/StatisticsWithAttribute.php
index f7541d45a581c8cd4dcd8b51abcbf16013be2c90..bcbdd20d815e70c0063ada4bca5b6b4b213f9744 100644
--- a/modules/core/lib/Auth/Process/StatisticsWithAttribute.php
+++ b/modules/core/lib/Auth/Process/StatisticsWithAttribute.php
@@ -20,17 +20,17 @@ class StatisticsWithAttribute extends Auth\ProcessingFilter
      * The attribute to log
      * @var string|null
      */
-    private $attribute = null;
+    private ?string $attribute = null;
 
     /**
      * @var string
      */
-    private $typeTag = 'saml20-idp-SSO';
+    private string $typeTag = 'saml20-idp-SSO';
 
     /**
      * @var bool
      */
-    private $skipPassive = false;
+    private bool $skipPassive = false;
 
 
     /**
diff --git a/modules/core/lib/Auth/Process/TargetedID.php b/modules/core/lib/Auth/Process/TargetedID.php
index 2325fa2f62a4310dc8b4678d0ed20a0062271205..04b6aefc2c59d78e24f259fb12d415484da7cca2 100644
--- a/modules/core/lib/Auth/Process/TargetedID.php
+++ b/modules/core/lib/Auth/Process/TargetedID.php
@@ -37,14 +37,14 @@ class TargetedID extends Auth\ProcessingFilter
      *
      * @var string
      */
-    private $identifyingAttribute;
+    private string $identifyingAttribute;
 
     /**
      * Whether the attribute should be generated as a NameID value, or as a simple string.
      *
      * @var boolean
      */
-    private $generateNameId = false;
+    private bool $generateNameId = false;
 
     /**
      * @var \SimpleSAML\Utils\Config|string
diff --git a/modules/core/lib/Auth/UserPassBase.php b/modules/core/lib/Auth/UserPassBase.php
index 515445b90cbadee35b3a3732df19ac7667932365..d43fc3d1ae0cd0cb066c862a86dd5211f911eef1 100644
--- a/modules/core/lib/Auth/UserPassBase.php
+++ b/modules/core/lib/Auth/UserPassBase.php
@@ -41,7 +41,7 @@ abstract class UserPassBase extends Auth\Source
      *
      * @var string|null
      */
-    private $forcedUsername;
+    private ?string $forcedUsername = null;
 
     /**
      * Links to pages from login page.
@@ -49,7 +49,7 @@ abstract class UserPassBase extends Auth\Source
      *
      * @var array
      */
-    protected $loginLinks = [];
+    protected array $loginLinks = [];
 
     /**
      * Storage for authsource config option remember.username.enabled
@@ -58,7 +58,7 @@ abstract class UserPassBase extends Auth\Source
      *
      * @var bool
      */
-    protected $rememberUsernameEnabled = false;
+    protected bool $rememberUsernameEnabled = false;
 
     /**
      * Storage for authsource config option remember.username.checked
@@ -67,7 +67,7 @@ abstract class UserPassBase extends Auth\Source
      *
      * @var bool
      */
-    protected $rememberUsernameChecked = false;
+    protected bool $rememberUsernameChecked = false;
 
     /**
      * Storage for general config option session.rememberme.enable.
@@ -78,7 +78,7 @@ abstract class UserPassBase extends Auth\Source
      *
      * @var bool
      */
-    protected $rememberMeEnabled = false;
+    protected bool $rememberMeEnabled = false;
 
     /**
      * Storage for general config option session.rememberme.checked.
@@ -87,7 +87,7 @@ abstract class UserPassBase extends Auth\Source
      *
      * @var bool
      */
-    protected $rememberMeChecked = false;
+    protected bool $rememberMeChecked = false;
 
 
     /**
diff --git a/modules/core/lib/Auth/UserPassOrgBase.php b/modules/core/lib/Auth/UserPassOrgBase.php
index 03b9b214a07c880a009dc6590d0c0ce135b084aa..df6cca39327a1338a7bf9cb0e2dc5d0edbc614da 100644
--- a/modules/core/lib/Auth/UserPassOrgBase.php
+++ b/modules/core/lib/Auth/UserPassOrgBase.php
@@ -47,7 +47,7 @@ abstract class UserPassOrgBase extends Auth\Source
      *
      * @var string
      */
-    private $usernameOrgMethod;
+    private string $usernameOrgMethod;
 
     /**
      * Storage for authsource config option remember.username.enabled
@@ -56,7 +56,7 @@ abstract class UserPassOrgBase extends Auth\Source
      *
      * @var bool
      */
-    protected $rememberUsernameEnabled = false;
+    protected bool $rememberUsernameEnabled = false;
 
     /**
      * Storage for authsource config option remember.username.checked
@@ -65,7 +65,7 @@ abstract class UserPassOrgBase extends Auth\Source
      *
      * @var bool
      */
-    protected $rememberUsernameChecked = false;
+    protected bool $rememberUsernameChecked = false;
 
     /**
      * Storage for authsource config option remember.organization.enabled
@@ -74,7 +74,7 @@ abstract class UserPassOrgBase extends Auth\Source
      *
      * @var bool
      */
-    protected $rememberOrganizationEnabled = false;
+    protected bool $rememberOrganizationEnabled = false;
 
     /**
      * Storage for authsource config option remember.organization.checked
@@ -83,7 +83,7 @@ abstract class UserPassOrgBase extends Auth\Source
      *
      * @var bool
      */
-    protected $rememberOrganizationChecked = false;
+    protected bool $rememberOrganizationChecked = false;
 
 
     /**
diff --git a/modules/core/lib/Controller/Exception.php b/modules/core/lib/Controller/Exception.php
index b872b377b26628eb43b1c5317ad6bf5f5b194a5c..1e5a093b73350f89882c0f7f3c299c961b2f51ab 100644
--- a/modules/core/lib/Controller/Exception.php
+++ b/modules/core/lib/Controller/Exception.php
@@ -25,10 +25,10 @@ use Symfony\Component\HttpFoundation\Response;
 class Exception
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
diff --git a/modules/core/lib/Controller/Login.php b/modules/core/lib/Controller/Login.php
index e54d60198cebecd0dd23505cb58779782fd8e7b7..a4941bc00fa12976abd3637e486405a52db31ef6 100644
--- a/modules/core/lib/Controller/Login.php
+++ b/modules/core/lib/Controller/Login.php
@@ -28,16 +28,16 @@ use Symfony\Component\HttpFoundation\Response;
 class Login
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Auth\AuthenticationFactory */
-    protected $factory;
+    protected AuthenticationFactory $factory;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
     /** @var array */
-    protected $sources;
+    protected array $sources;
 
 
     /**
diff --git a/modules/core/lib/Controller/Redirection.php b/modules/core/lib/Controller/Redirection.php
index 373f77bff681b4bd23059069424222a3df806539..942dd675c1a3369cd6930de8e110ffbd22c72b36 100644
--- a/modules/core/lib/Controller/Redirection.php
+++ b/modules/core/lib/Controller/Redirection.php
@@ -26,10 +26,10 @@ use Symfony\Component\HttpFoundation\Response;
 class Redirection
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
diff --git a/modules/core/lib/Stats/Output/File.php b/modules/core/lib/Stats/Output/File.php
index 17d890bc707be51e865efbe91b76d991e87284da..263c7001b357029bb9087f555e2649fec574bc8e 100644
--- a/modules/core/lib/Stats/Output/File.php
+++ b/modules/core/lib/Stats/Output/File.php
@@ -19,7 +19,7 @@ class File extends \SimpleSAML\Stats\Output
      * The log directory.
      * @var string
      */
-    private $logDir;
+    private string $logDir;
 
     /**
      * The file handle for the current file.
@@ -31,7 +31,7 @@ class File extends \SimpleSAML\Stats\Output
      * The current file date.
      * @var string|null
      */
-    private $fileDate = null;
+    private ?string $fileDate = null;
 
 
     /**
diff --git a/modules/core/lib/Storage/SQLPermanentStorage.php b/modules/core/lib/Storage/SQLPermanentStorage.php
index 183a38b658e1f1a4eb7d3d0d0440954f2c735945..7c21976aa743d17207a270715e4209d8b6fd4a67 100644
--- a/modules/core/lib/Storage/SQLPermanentStorage.php
+++ b/modules/core/lib/Storage/SQLPermanentStorage.php
@@ -19,7 +19,7 @@ use SimpleSAML\Configuration;
 class SQLPermanentStorage
 {
     /** @var \PDO */
-    private $db;
+    private PDO $db;
 
 
     /**
diff --git a/modules/cron/lib/Controller/Cron.php b/modules/cron/lib/Controller/Cron.php
index b7de7617958dc6ba49cfffeb7f3b610307e44f7b..0b6542d7f5862d4070682595e59f641f50f6d8f7 100644
--- a/modules/cron/lib/Controller/Cron.php
+++ b/modules/cron/lib/Controller/Cron.php
@@ -29,13 +29,13 @@ use Symfony\Component\HttpFoundation\Response;
 class Cron
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Configuration */
-    protected $cronconfig;
+    protected Configuration $cronconfig;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
     /**
      * @var \SimpleSAML\Utils\Auth|string
diff --git a/modules/cron/lib/Cron.php b/modules/cron/lib/Cron.php
index 7c6b0c50f0be0c0dec9c674012f43619fc7810c6..b6f7b43f9aa272409353da156a1a9b7f11a7afad 100644
--- a/modules/cron/lib/Cron.php
+++ b/modules/cron/lib/Cron.php
@@ -19,7 +19,7 @@ class Cron
      * The configuration for the Cron module
      * @var \SimpleSAML\Configuration
      */
-    private $cronconfig;
+    private Configuration $cronconfig;
 
 
     /*
diff --git a/modules/exampleauth/lib/Auth/Source/StaticSource.php b/modules/exampleauth/lib/Auth/Source/StaticSource.php
index 270d6c0ed556923f34ef6158864eed099f19f67c..fc047932230c450258c5eec79e4413887f09af35 100644
--- a/modules/exampleauth/lib/Auth/Source/StaticSource.php
+++ b/modules/exampleauth/lib/Auth/Source/StaticSource.php
@@ -23,7 +23,7 @@ class StaticSource extends Auth\Source
      * The attributes we return.
      * @var array
      */
-    private $attributes;
+    private array $attributes;
 
 
     /**
diff --git a/modules/exampleauth/lib/Auth/Source/UserPass.php b/modules/exampleauth/lib/Auth/Source/UserPass.php
index a7a19adee7a9b86c8581d3c826aacd3341a8476d..e2d08094cdec50b788b5dbb21212147611b99873 100644
--- a/modules/exampleauth/lib/Auth/Source/UserPass.php
+++ b/modules/exampleauth/lib/Auth/Source/UserPass.php
@@ -27,7 +27,7 @@ class UserPass extends UserPassBase
      *
      * @var array
      */
-    private $users;
+    private array $users;
 
 
     /**
diff --git a/modules/multiauth/lib/Auth/Source/MultiAuth.php b/modules/multiauth/lib/Auth/Source/MultiAuth.php
index 3304ad27456f44b64a255af4b986b9767e1a97ea..2ad0482b1a20a6905a61fbfa81f32c248a8d05b0 100644
--- a/modules/multiauth/lib/Auth/Source/MultiAuth.php
+++ b/modules/multiauth/lib/Auth/Source/MultiAuth.php
@@ -48,12 +48,12 @@ class MultiAuth extends Auth\Source
      * Array of sources we let the user chooses among.
      * @var array
      */
-    private $sources;
+    private array $sources;
 
     /**
      * @var string|null preselect source in filter module configuration
      */
-    private $preselect;
+    private ?string $preselect;
 
 
     /**
diff --git a/modules/multiauth/lib/Controller/DiscoController.php b/modules/multiauth/lib/Controller/DiscoController.php
index e4d3eba97124092c83cfff739e28997d37330c18..efc685482f8ddb962bbb943d19eb15ac8e22716f 100644
--- a/modules/multiauth/lib/Controller/DiscoController.php
+++ b/modules/multiauth/lib/Controller/DiscoController.php
@@ -26,10 +26,10 @@ use Symfony\Component\HttpFoundation\Request;
 class DiscoController
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
     /**
      * @var \SimpleSAML\Auth\Source|string
diff --git a/modules/saml/docs/sp.md b/modules/saml/docs/sp.md
index bda37fea1540616686534d6fcd54a876b32b3c33..fc4eeb420a1cca496de64e87b46b5ad9da57881e 100644
--- a/modules/saml/docs/sp.md
+++ b/modules/saml/docs/sp.md
@@ -26,7 +26,6 @@ All these parameters override the equivalent option from the configuration.
 `saml:AuthnContextClassRef`
 :   The AuthnContextClassRef that will be sent in the login request.
 
-:   *Note*: SAML 2 specific.
 
 `saml:AuthnContextComparison`
 :   The Comparison attribute of the AuthnContext that will be sent in the login request.
@@ -38,12 +37,10 @@ All these parameters override the equivalent option from the configuration.
     * `SAML2\Constants::COMPARISON_MINIMUM`
     * `SAML2\Constants::COMPARISON_MAXIMUM`
     
-:   *Note*: SAML 2 specific.
 
 `ForceAuthn`
 :   Force authentication allows you to force re-authentication of users even if the user has a SSO session at the IdP.
 
-:   *Note*: SAML 2 specific.
 
 `saml:idp`
 :   The entity ID of the IdP we should send an authentication request to.
@@ -51,18 +48,15 @@ All these parameters override the equivalent option from the configuration.
 `isPassive`
 :   Send a passive authentication request.
 
-:   *Note*: SAML 2 specific.
 
 `saml:Extensions`
 :   The samlp:Extensions that will be sent in the login request.
 
-:   *Note*: SAML 2 specific.
 
 `saml:NameID`
 :   Add a Subject element with a NameID to the SAML AuthnRequest for the IdP.
     This must be a \SAML2\XML\saml\NameID object.
 
-:   *Note*: SAML 2 specific.
 
 `saml:NameIDPolicy`
 :   The format of the NameID we request from the IdP: an array in the form of
@@ -73,13 +67,11 @@ All these parameters override the equivalent option from the configuration.
 :   For compatibility purposes, `null` is equivalent to transient and a format
     can be defined as a string instead of an array. These variants are deprecated.
 
-:   *Note*: SAML 2 specific.
 
 `saml:Audience`
 :   Add a Conditions element to the SAML AuthnRequest containing an
     AudienceRestriction with one or more audiences.
 
-:   *Note*: SAML 2 specific.
 
 
 Authentication data
@@ -119,7 +111,6 @@ Options
 
 :   Note that this option can be overridden for a specific IdP in saml20-idp-remote.
 
-:   *Note*: SAML 2 specific.
 
 `AssertionConsumerService`
 :   List of Assertion Consumer Services in the generated metadata. Specified in the array of
@@ -161,7 +152,6 @@ Options
 :   The SP can request authentication with a specific authentication context class.
     One example of usage could be if the IdP supports both username/password authentication as well as software-PKI.
 
-:   *Note*: SAML 2 specific.
 
 `AuthnContextComparison`
 :   The Comparison attribute of the AuthnContext that will be sent in the login request.
@@ -173,7 +163,6 @@ Options
     * `SAML2\Constants::COMPARISON_MINIMUM`
     * `SAML2\Constants::COMPARISON_MAXIMUM`
     
-:   *Note*: SAML 2 specific.
 
 `authproc`
 :   Processing filters that should be run after SP authentication.
@@ -236,7 +225,6 @@ Options
 
 :   Note that this option can be set for each IdP in the [IdP-remote metadata](./simplesamlphp-reference-idp-remote).
 
-:   *Note*: SAML 2 specific.
 
 `entityID`
 :   The entity ID this SP should use.
@@ -247,7 +235,6 @@ Options
 `ForceAuthn`
 :   Force authentication allows you to force re-authentication of users even if the user has a SSO session at the IdP.
 
-:   *Note*: SAML 2 specific.
 
 `idp`
 :   The entity ID this SP should connect to.
@@ -257,7 +244,6 @@ Options
 `IsPassive`
 :   IsPassive allows you to enable passive authentication by default for this SP.
 
-:   *Note*: SAML 2 specific.
 
 `name`
 :   The name of this SP.
@@ -278,7 +264,6 @@ Options
 
 :   Note that this option can be set for each IdP in the [IdP-remote metadata](./simplesamlphp-reference-idp-remote).
 
-:   *Note*: SAML 2 specific.
 
 `NameIDPolicy`
 :   The format of the NameID we request from the idp: an array in the form of
@@ -289,7 +274,6 @@ Options
 :   For compatibility purposes, `null` is equivalent to transient and a format
     can be defined as a string instead of an array. These variants are deprecated.
 
-:   *Note*: SAML 2 specific.
 
 `OrganizationName`
 :   The name of the organization responsible for this SP.
@@ -323,36 +307,30 @@ Options
 `privatekey`
 :   File name of private key to be used for signing messages and decrypting messages from the IdP. This option is only required if you use encrypted assertions or if you enable signing of messages.
 
-:   *Note*: SAML 2 specific.
 
 `privatekey_pass`
 :   The passphrase for the private key, if it is encrypted. If the private key is unencrypted, this can be left out.
 
-:   *Note*: SAML 2 specific.
 
 `ProviderName`
 :   Human readable name of the local SP sent with the authentication request.
 
-:   *Note*: SAML 2 specific.
 
 `ProtocolBinding`
 :   The binding that should be used for SAML2 authentication responses.
     This option controls the binding that is requested through the AuthnRequest message to the IdP.
     By default the HTTP-Post binding is used.
 
-:   *Note*: SAML 2 specific.
 
 `redirect.sign`
 :   Whether authentication requests, logout requests and logout responses sent from this SP should be signed. The default is `FALSE`.
     If set, the `AuthnRequestsSigned` attribute of the `SPSSODescriptor` element in SAML 2.0 metadata will contain its value. This
     option takes precedence over the `sign.authnrequest` option in any metadata generated for this SP.
 
-:   *Note*: SAML 2 specific.
 
 `redirect.validate`
 :   Whether logout requests and logout responses received by this SP should be validated. The default is `FALSE`.
 
-:   *Note*: SAML 2 specific.
 
 `RegistrationInfo`
 :   Allows to specify information about the registrar of this SP. Please refer to the
@@ -361,7 +339,6 @@ Options
 `RelayState`
 :   The page the user should be redirected to after an IdP initiated SSO.
 
-:   *Note*: SAML 2 specific.
 
 `saml.SOAPClient.certificate`
 :   A file with a certificate _and_ private key that should be used when issuing SOAP requests from this SP.
@@ -384,7 +361,6 @@ Options
     any value in the IdP-remote metadata overrides the one configured
     in the SP configuration.
 
-:   *Note*: SAML 2 specific.
 
 `sign.logout`
 :   Whether to sign logout messages sent from this SP.
@@ -393,7 +369,6 @@ Options
     any value in the IdP-remote metadata overrides the one configured
     in the SP configuration.
 
-:   *Note*: SAML 2 specific.
 
 `signature.algorithm`
 :   The algorithm to use when signing any message generated by this service provider. Defaults to RSA-SHA256.
@@ -407,12 +382,12 @@ Options
     * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
 
 `SingleLogoutServiceBinding`
-:	List of SingleLogoutService bindings the IdP will claim support for.
+:	List of SingleLogoutService bindings the SP will claim support for (can be empty).
 :	Possible values:
 
     * `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect`
     * `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
-	* `urn:oasis:names:tc:SAML:2.0:bindings:SOAP`
+    * `urn:oasis:names:tc:SAML:2.0:bindings:SOAP`
 
 `SingleLogoutServiceLocation`
 :   The Single Logout Service URL published in the generated metadata.
@@ -434,7 +409,6 @@ Options
     any value in the IdP-remote metadata overrides the one configured
     in the IdP metadata.
 
-:   *Note*: SAML 2 specific.
 
 `WantAssertionsSigned`
 :   Whether assertions received by this SP must be signed. The default value is `FALSE`.
diff --git a/modules/saml/lib/Auth/Process/AttributeNameID.php b/modules/saml/lib/Auth/Process/AttributeNameID.php
index e840f2b6c21b0e4890646b6ace5710d229dc0392..0c3eae84667144c9885b671367c2788db85bdaac 100644
--- a/modules/saml/lib/Auth/Process/AttributeNameID.php
+++ b/modules/saml/lib/Auth/Process/AttributeNameID.php
@@ -22,7 +22,7 @@ class AttributeNameID extends BaseNameIDGenerator
      *
      * @var string
      */
-    private $attribute;
+    private string $attribute;
 
 
     /**
diff --git a/modules/saml/lib/Auth/Process/AuthnContextClassRef.php b/modules/saml/lib/Auth/Process/AuthnContextClassRef.php
index 93bf1c7197364510604f7d6909f0b30b0a7ebfc5..bb46319b10ebd0d88b8812327134504030a5d15f 100644
--- a/modules/saml/lib/Auth/Process/AuthnContextClassRef.php
+++ b/modules/saml/lib/Auth/Process/AuthnContextClassRef.php
@@ -20,7 +20,7 @@ class AuthnContextClassRef extends ProcessingFilter
      *
      * @var string|null
      */
-    private $authnContextClassRef = null;
+    private ?string $authnContextClassRef = null;
 
 
     /**
diff --git a/modules/saml/lib/Auth/Process/ExpectedAuthnContextClassRef.php b/modules/saml/lib/Auth/Process/ExpectedAuthnContextClassRef.php
index 31db71085b5d82a350fe62e8080aacbd318ad777..c4409880803d5fe2dd9f57555d023a3e0b4c4ec2 100644
--- a/modules/saml/lib/Auth/Process/ExpectedAuthnContextClassRef.php
+++ b/modules/saml/lib/Auth/Process/ExpectedAuthnContextClassRef.php
@@ -34,14 +34,14 @@ class ExpectedAuthnContextClassRef extends ProcessingFilter
      * Array of accepted AuthnContextClassRef
      * @var array
      */
-    private $accepted;
+    private array $accepted;
 
 
     /**
      * AuthnContextClassRef of the assertion
      * @var string|null
      */
-    private $AuthnContextClassRef = null;
+    private ?string $AuthnContextClassRef = null;
 
 
     /**
diff --git a/modules/saml/lib/Auth/Process/FilterScopes.php b/modules/saml/lib/Auth/Process/FilterScopes.php
index 3a80036386cad1aa662d3e2f8b0e5aaa4ede432f..9748a9c614208d0912d364d42ea10ad4061f487f 100644
--- a/modules/saml/lib/Auth/Process/FilterScopes.php
+++ b/modules/saml/lib/Auth/Process/FilterScopes.php
@@ -18,9 +18,9 @@ use SimpleSAML\Utils;
 class FilterScopes extends ProcessingFilter
 {
     /**
-     * @var array Stores any pre-configured scoped attributes which come from the filter configuration.
+     * @var string[]  Stores any pre-configured scoped attributes which come from the filter configuration.
      */
-    private $scopedAttributes = [
+    private array $scopedAttributes = [
         'eduPersonScopedAffiliation',
         'eduPersonPrincipalName'
     ];
diff --git a/modules/saml/lib/Auth/Process/NameIDAttribute.php b/modules/saml/lib/Auth/Process/NameIDAttribute.php
index 33e612eecfc0a1fc5d4702b1e888d8168f394f99..0037d045626d105ff4815dd9be17c0d754b22976 100644
--- a/modules/saml/lib/Auth/Process/NameIDAttribute.php
+++ b/modules/saml/lib/Auth/Process/NameIDAttribute.php
@@ -22,7 +22,7 @@ class NameIDAttribute extends ProcessingFilter
      *
      * @var string
      */
-    private $attribute;
+    private string $attribute;
 
 
     /**
@@ -30,7 +30,7 @@ class NameIDAttribute extends ProcessingFilter
      *
      * @var array
      */
-    private $format;
+    private array $format;
 
 
     /**
diff --git a/modules/saml/lib/Auth/Process/PersistentNameID.php b/modules/saml/lib/Auth/Process/PersistentNameID.php
index f54b2153216d3e7ddc4c845838280ac2d3f5405e..b7f825a69ded7d71e84afffb2f1be58d39ab8c66 100644
--- a/modules/saml/lib/Auth/Process/PersistentNameID.php
+++ b/modules/saml/lib/Auth/Process/PersistentNameID.php
@@ -24,7 +24,7 @@ class PersistentNameID extends BaseNameIDGenerator
      *
      * @var string
      */
-    private $attribute;
+    private string $attribute;
 
 
     /**
diff --git a/modules/saml/lib/Auth/Process/PersistentNameID2TargetedID.php b/modules/saml/lib/Auth/Process/PersistentNameID2TargetedID.php
index 99053c352d461421a228b52249750a332f7c167e..e713827e5bbc301eeab0c3987249035e24e45e2e 100644
--- a/modules/saml/lib/Auth/Process/PersistentNameID2TargetedID.php
+++ b/modules/saml/lib/Auth/Process/PersistentNameID2TargetedID.php
@@ -22,7 +22,7 @@ class PersistentNameID2TargetedID extends ProcessingFilter
      *
      * @var string
      */
-    private $attribute;
+    private string $attribute;
 
 
     /**
@@ -30,7 +30,7 @@ class PersistentNameID2TargetedID extends ProcessingFilter
      *
      * @var bool
      */
-    private $nameId;
+    private bool $nameId;
 
 
     /**
diff --git a/modules/saml/lib/Auth/Process/SQLPersistentNameID.php b/modules/saml/lib/Auth/Process/SQLPersistentNameID.php
index 2e2bd639dd23aab72764eee0ed8760a6de00d48d..60e8a0223335979768ba38a82fe34c908f7887d9 100644
--- a/modules/saml/lib/Auth/Process/SQLPersistentNameID.php
+++ b/modules/saml/lib/Auth/Process/SQLPersistentNameID.php
@@ -23,35 +23,35 @@ class SQLPersistentNameID extends BaseNameIDGenerator
      *
      * @var string
      */
-    private $attribute;
+    private string $attribute;
 
     /**
      * Whether we should create a persistent NameID if not explicitly requested (as saml:PersistentNameID does).
      *
      * @var boolean
      */
-    private $allowUnspecified = false;
+    private bool $allowUnspecified = false;
 
     /**
      * Whether we should create a persistent NameID if a different format is requested.
      *
      * @var boolean
      */
-    private $allowDifferent = false;
+    private bool $allowDifferent = false;
 
     /**
      * Whether we should ignore allowCreate in the NameID policy
      *
      * @var boolean
      */
-    private $alwaysCreate = false;
+    private bool $alwaysCreate = false;
 
     /**
      * Database store configuration.
      *
      * @var array
      */
-    private $storeConfig = [];
+    private array $storeConfig = [];
 
 
     /**
diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php
index 4f633ccc4d58386dc634ff66a320a2298ca27e54..9a159796a9978ab1cd53199b23693b94bf439968 100644
--- a/modules/saml/lib/Auth/Source/SP.php
+++ b/modules/saml/lib/Auth/Source/SP.php
@@ -27,42 +27,42 @@ class SP extends \SimpleSAML\Auth\Source
      *
      * @var string
      */
-    private $entityId;
+    private string $entityId;
 
     /**
      * The metadata of this SP.
      *
      * @var \SimpleSAML\Configuration
      */
-    private $metadata;
+    private Configuration $metadata;
 
     /**
      * The IdP the user is allowed to log into.
      *
      * @var string|null  The IdP the user can log into, or null if the user can log into all IdPs.
      */
-    private $idp;
+    private ?string $idp;
 
     /**
      * URL to discovery service.
      *
      * @var string|null
      */
-    private $discoURL;
+    private ?string $discoURL;
 
     /**
      * Flag to indicate whether to disable sending the Scoping element.
      *
      * @var bool
      */
-    private $disable_scoping;
+    private bool $disable_scoping;
 
     /**
      * A list of supported protocols.
      *
      * @var string[]
      */
-    private $protocols = [];
+    private array $protocols = [];
 
 
     /**
@@ -264,7 +264,7 @@ class SP extends \SimpleSAML\Auth\Source
         }
 
         // add signature options
-        if ($this->metadata->hasValue('WantAssertiosnsSigned')) {
+        if ($this->metadata->hasValue('WantAssertionsSigned')) {
             $metadata['saml20.sign.assertion'] = $this->metadata->getBoolean('WantAssertionsSigned');
         }
         if ($this->metadata->hasValue('redirect.sign')) {
diff --git a/modules/saml/lib/BaseNameIDGenerator.php b/modules/saml/lib/BaseNameIDGenerator.php
index c319ea450d607c5c30a55369c05da85029c99ff6..7c8d29d8336d93b1f0bdb23756f88b6158525c1f 100644
--- a/modules/saml/lib/BaseNameIDGenerator.php
+++ b/modules/saml/lib/BaseNameIDGenerator.php
@@ -46,7 +46,7 @@ abstract class BaseNameIDGenerator extends \SimpleSAML\Auth\ProcessingFilter
      *
      * @var string|null
      */
-    protected $format = null;
+    protected ?string $format = null;
 
 
     /**
diff --git a/modules/saml/lib/Error.php b/modules/saml/lib/Error.php
index c5101edb3f2ddd9aa2762b5c6fbfbf2c23e7b8b0..7a4655470615f4d24b028e88cce6310136377baa 100644
--- a/modules/saml/lib/Error.php
+++ b/modules/saml/lib/Error.php
@@ -21,21 +21,21 @@ class Error extends \SimpleSAML\Error\Exception
      *
      * @var string
      */
-    private $status;
+    private string $status;
 
     /**
      * The second-level status code, or NULL if no second-level status code is defined.
      *
      * @var string|null
      */
-    private $subStatus;
+    private ?string $subStatus;
 
     /**
      * The status message, or NULL if no status message is defined.
      *
      * @var string|null
      */
-    private $statusMessage;
+    private ?string $statusMessage;
 
 
     /**
diff --git a/package-lock.json b/package-lock.json
index 61d5eb66d5a9ace1c434c4c0bb322150beccf8ad..9d9518c2a432d28d32d424e44bce285f1767332a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,42 +4,41 @@
   "lockfileVersion": 1,
   "dependencies": {
     "@babel/code-frame": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-      "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+      "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
       "dev": true,
       "requires": {
         "@babel/highlight": "^7.10.4"
       }
     },
     "@babel/core": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.0.tgz",
-      "integrity": "sha512-mkLq8nwaXmDtFmRkQ8ED/eA2CnVw4zr7dCztKalZXBvdK5EeNUAesrrwUqjQEzFgomJssayzB0aqlOsP1vGLqg==",
+      "version": "7.12.10",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz",
+      "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.10.4",
-        "@babel/generator": "^7.11.0",
-        "@babel/helper-module-transforms": "^7.11.0",
-        "@babel/helpers": "^7.10.4",
-        "@babel/parser": "^7.11.0",
-        "@babel/template": "^7.10.4",
-        "@babel/traverse": "^7.11.0",
-        "@babel/types": "^7.11.0",
+        "@babel/generator": "^7.12.10",
+        "@babel/helper-module-transforms": "^7.12.1",
+        "@babel/helpers": "^7.12.5",
+        "@babel/parser": "^7.12.10",
+        "@babel/template": "^7.12.7",
+        "@babel/traverse": "^7.12.10",
+        "@babel/types": "^7.12.10",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.1",
         "json5": "^2.1.2",
         "lodash": "^4.17.19",
-        "resolve": "^1.3.2",
         "semver": "^5.4.1",
         "source-map": "^0.5.0"
       },
       "dependencies": {
         "json5": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
-          "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+          "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
           "dev": true,
           "requires": {
             "minimist": "^1.2.5"
@@ -48,124 +47,125 @@
       }
     },
     "@babel/generator": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz",
-      "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz",
+      "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.11.0",
+        "@babel/types": "^7.12.11",
         "jsesc": "^2.5.1",
         "source-map": "^0.5.0"
       }
     },
     "@babel/helper-function-name": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
-      "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz",
+      "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==",
       "dev": true,
       "requires": {
-        "@babel/helper-get-function-arity": "^7.10.4",
-        "@babel/template": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/helper-get-function-arity": "^7.12.10",
+        "@babel/template": "^7.12.7",
+        "@babel/types": "^7.12.11"
       }
     },
     "@babel/helper-get-function-arity": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
-      "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+      "version": "7.12.10",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz",
+      "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.10"
       }
     },
     "@babel/helper-member-expression-to-functions": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
-      "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+      "version": "7.12.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz",
+      "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.11.0"
+        "@babel/types": "^7.12.7"
       }
     },
     "@babel/helper-module-imports": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
-      "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz",
+      "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.5"
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
-      "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz",
+      "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==",
       "dev": true,
       "requires": {
-        "@babel/helper-module-imports": "^7.10.4",
-        "@babel/helper-replace-supers": "^7.10.4",
-        "@babel/helper-simple-access": "^7.10.4",
+        "@babel/helper-module-imports": "^7.12.1",
+        "@babel/helper-replace-supers": "^7.12.1",
+        "@babel/helper-simple-access": "^7.12.1",
         "@babel/helper-split-export-declaration": "^7.11.0",
+        "@babel/helper-validator-identifier": "^7.10.4",
         "@babel/template": "^7.10.4",
-        "@babel/types": "^7.11.0",
+        "@babel/traverse": "^7.12.1",
+        "@babel/types": "^7.12.1",
         "lodash": "^4.17.19"
       }
     },
     "@babel/helper-optimise-call-expression": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
-      "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+      "version": "7.12.10",
+      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz",
+      "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.10"
       }
     },
     "@babel/helper-replace-supers": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
-      "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz",
+      "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==",
       "dev": true,
       "requires": {
-        "@babel/helper-member-expression-to-functions": "^7.10.4",
-        "@babel/helper-optimise-call-expression": "^7.10.4",
-        "@babel/traverse": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/helper-member-expression-to-functions": "^7.12.7",
+        "@babel/helper-optimise-call-expression": "^7.12.10",
+        "@babel/traverse": "^7.12.10",
+        "@babel/types": "^7.12.11"
       }
     },
     "@babel/helper-simple-access": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
-      "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+      "version": "7.12.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz",
+      "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==",
       "dev": true,
       "requires": {
-        "@babel/template": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/types": "^7.12.1"
       }
     },
     "@babel/helper-split-export-declaration": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
-      "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz",
+      "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.11.0"
+        "@babel/types": "^7.12.11"
       }
     },
     "@babel/helper-validator-identifier": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
-      "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
+      "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
       "dev": true
     },
     "@babel/helpers": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz",
-      "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==",
+      "version": "7.12.5",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz",
+      "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==",
       "dev": true,
       "requires": {
         "@babel/template": "^7.10.4",
-        "@babel/traverse": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/traverse": "^7.12.5",
+        "@babel/types": "^7.12.5"
       }
     },
     "@babel/highlight": {
@@ -180,88 +180,89 @@
       }
     },
     "@babel/parser": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.0.tgz",
-      "integrity": "sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw==",
+      "version": "7.12.11",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz",
+      "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==",
       "dev": true
     },
     "@babel/template": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
-      "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+      "version": "7.12.7",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz",
+      "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.10.4",
-        "@babel/parser": "^7.10.4",
-        "@babel/types": "^7.10.4"
+        "@babel/parser": "^7.12.7",
+        "@babel/types": "^7.12.7"
       }
     },
     "@babel/traverse": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz",
-      "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==",
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz",
+      "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.10.4",
-        "@babel/generator": "^7.11.0",
-        "@babel/helper-function-name": "^7.10.4",
-        "@babel/helper-split-export-declaration": "^7.11.0",
-        "@babel/parser": "^7.11.0",
-        "@babel/types": "^7.11.0",
+        "@babel/code-frame": "^7.12.11",
+        "@babel/generator": "^7.12.11",
+        "@babel/helper-function-name": "^7.12.11",
+        "@babel/helper-split-export-declaration": "^7.12.11",
+        "@babel/parser": "^7.12.11",
+        "@babel/types": "^7.12.12",
         "debug": "^4.1.0",
         "globals": "^11.1.0",
         "lodash": "^4.17.19"
       }
     },
     "@babel/types": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
-      "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
+      "version": "7.12.12",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz",
+      "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-validator-identifier": "^7.10.4",
+        "@babel/helper-validator-identifier": "^7.12.11",
         "lodash": "^4.17.19",
         "to-fast-properties": "^2.0.0"
       }
     },
     "@fortawesome/fontawesome-free": {
-      "version": "5.14.0",
-      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.14.0.tgz",
-      "integrity": "sha512-OfdMsF+ZQgdKHP9jUbmDcRrP0eX90XXrsXIdyjLbkmSBzmMXPABB8eobUJtivaupucYaByz6WNe1PI1JuYm3qA=="
+      "version": "5.15.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.2.tgz",
+      "integrity": "sha512-7l/AX41m609L/EXI9EKH3Vs3v0iA8tKlIOGtw+kgcoanI7p+e4I4GYLqW3UXWiTnjSFymKSmTTPKYrivzbxxqA=="
     },
     "@nodelib/fs.scandir": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
-      "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==",
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+      "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
       "dev": true,
       "requires": {
-        "@nodelib/fs.stat": "2.0.3",
+        "@nodelib/fs.stat": "2.0.4",
         "run-parallel": "^1.1.9"
       }
     },
     "@nodelib/fs.stat": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
-      "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+      "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
       "dev": true
     },
     "@nodelib/fs.walk": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz",
-      "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==",
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+      "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
       "dev": true,
       "requires": {
-        "@nodelib/fs.scandir": "2.1.3",
+        "@nodelib/fs.scandir": "2.1.4",
         "fastq": "^1.6.0"
       }
     },
     "@npmcli/move-file": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz",
-      "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.1.tgz",
+      "integrity": "sha512-LtWTicuF2wp7PNTuyCwABx7nNG+DnzSE8gN0iWxkC6mpgm/iOPu0ZMTkXuCxmJxtWFsDxUaixM9COSNJEMUfuQ==",
       "dev": true,
       "requires": {
-        "mkdirp": "^1.0.4"
+        "mkdirp": "^1.0.4",
+        "rimraf": "^3.0.2"
       },
       "dependencies": {
         "mkdirp": {
@@ -269,6 +270,15 @@
           "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
           "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
           "dev": true
+        },
+        "rimraf": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
         }
       }
     },
@@ -472,15 +482,20 @@
       "dev": true
     },
     "acorn": {
-      "version": "6.4.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
-      "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
+      "version": "6.4.2",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+      "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
       "dev": true
     },
+    "after": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+      "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
+    },
     "aggregate-error": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
-      "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
       "dev": true,
       "requires": {
         "clean-stack": "^2.0.0",
@@ -496,12 +511,12 @@
       }
     },
     "ajv": {
-      "version": "6.10.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
-      "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
       "dev": true,
       "requires": {
-        "fast-deep-equal": "^2.0.1",
+        "fast-deep-equal": "^3.1.1",
         "fast-json-stable-stringify": "^2.0.0",
         "json-schema-traverse": "^0.4.1",
         "uri-js": "^4.2.2"
@@ -618,14 +633,15 @@
       }
     },
     "asn1.js": {
-      "version": "4.10.1",
-      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
-      "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+      "version": "5.4.1",
+      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+      "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
       "dev": true,
       "requires": {
         "bn.js": "^4.0.0",
         "inherits": "^2.0.1",
-        "minimalistic-assert": "^1.0.0"
+        "minimalistic-assert": "^1.0.0",
+        "safer-buffer": "^2.1.0"
       },
       "dependencies": {
         "bn.js": {
@@ -721,15 +737,14 @@
       "dev": true
     },
     "babel-loader": {
-      "version": "8.1.0",
-      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz",
-      "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==",
+      "version": "8.2.2",
+      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz",
+      "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==",
       "dev": true,
       "requires": {
-        "find-cache-dir": "^2.1.0",
+        "find-cache-dir": "^3.3.1",
         "loader-utils": "^1.4.0",
-        "mkdirp": "^0.5.3",
-        "pify": "^4.0.1",
+        "make-dir": "^3.1.0",
         "schema-utils": "^2.6.5"
       },
       "dependencies": {
@@ -814,9 +829,9 @@
       }
     },
     "base64-js": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
-      "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==",
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
       "dev": true
     },
     "bcrypt-pbkdf": {
@@ -835,12 +850,32 @@
       "dev": true
     },
     "binary-extensions": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
-      "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
       "dev": true,
       "optional": true
     },
+    "bl": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.1.tgz",
+      "integrity": "sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==",
+      "requires": {
+        "readable-stream": "^3.0.1"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
+      }
+    },
     "block-stream": {
       "version": "0.0.9",
       "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -857,9 +892,9 @@
       "dev": true
     },
     "bn.js": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
-      "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==",
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
+      "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
       "dev": true
     },
     "brace-expansion": {
@@ -945,34 +980,26 @@
       }
     },
     "browserify-rsa": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
-      "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
+      "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
       "dev": true,
       "requires": {
-        "bn.js": "^4.1.0",
+        "bn.js": "^5.0.0",
         "randombytes": "^2.0.1"
-      },
-      "dependencies": {
-        "bn.js": {
-          "version": "4.11.9",
-          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
-          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
-          "dev": true
-        }
       }
     },
     "browserify-sign": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz",
-      "integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==",
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
+      "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
       "dev": true,
       "requires": {
         "bn.js": "^5.1.1",
         "browserify-rsa": "^4.0.1",
         "create-hash": "^1.2.0",
         "create-hmac": "^1.1.7",
-        "elliptic": "^6.5.2",
+        "elliptic": "^6.5.3",
         "inherits": "^2.0.4",
         "parse-asn1": "^5.1.5",
         "readable-stream": "^3.6.0",
@@ -1037,26 +1064,59 @@
       "dev": true
     },
     "cacache": {
-      "version": "12.0.4",
-      "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
-      "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+      "version": "15.0.5",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz",
+      "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==",
       "dev": true,
       "requires": {
-        "bluebird": "^3.5.5",
-        "chownr": "^1.1.1",
-        "figgy-pudding": "^3.5.1",
+        "@npmcli/move-file": "^1.0.1",
+        "chownr": "^2.0.0",
+        "fs-minipass": "^2.0.0",
         "glob": "^7.1.4",
-        "graceful-fs": "^4.1.15",
-        "infer-owner": "^1.0.3",
-        "lru-cache": "^5.1.1",
-        "mississippi": "^3.0.0",
-        "mkdirp": "^0.5.1",
-        "move-concurrently": "^1.0.1",
+        "infer-owner": "^1.0.4",
+        "lru-cache": "^6.0.0",
+        "minipass": "^3.1.1",
+        "minipass-collect": "^1.0.2",
+        "minipass-flush": "^1.0.5",
+        "minipass-pipeline": "^1.2.2",
+        "mkdirp": "^1.0.3",
+        "p-map": "^4.0.0",
         "promise-inflight": "^1.0.1",
-        "rimraf": "^2.6.3",
-        "ssri": "^6.0.1",
-        "unique-filename": "^1.1.1",
-        "y18n": "^4.0.0"
+        "rimraf": "^3.0.2",
+        "ssri": "^8.0.0",
+        "tar": "^6.0.2",
+        "unique-filename": "^1.1.1"
+      },
+      "dependencies": {
+        "mkdirp": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+          "dev": true
+        },
+        "rimraf": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "tar": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
+          "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
+          "dev": true,
+          "requires": {
+            "chownr": "^2.0.0",
+            "fs-minipass": "^2.0.0",
+            "minipass": "^3.0.0",
+            "minizlib": "^2.1.1",
+            "mkdirp": "^1.0.3",
+            "yallist": "^4.0.0"
+          }
+        }
       }
     },
     "cache-base": {
@@ -1127,20 +1187,20 @@
       }
     },
     "chokidar": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz",
-      "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==",
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
+      "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
       "dev": true,
       "optional": true,
       "requires": {
         "anymatch": "~3.1.1",
         "braces": "~3.0.2",
-        "fsevents": "~2.1.2",
+        "fsevents": "~2.3.1",
         "glob-parent": "~5.1.0",
         "is-binary-path": "~2.1.0",
         "is-glob": "~4.0.1",
         "normalize-path": "~3.0.0",
-        "readdirp": "~3.4.0"
+        "readdirp": "~3.5.0"
       },
       "dependencies": {
         "braces": {
@@ -1163,16 +1223,6 @@
             "to-regex-range": "^5.0.1"
           }
         },
-        "glob-parent": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
-          "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "is-glob": "^4.0.1"
-          }
-        },
         "is-number": {
           "version": "7.0.0",
           "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -1193,9 +1243,9 @@
       }
     },
     "chownr": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+      "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
       "dev": true
     },
     "chrome-trace-event": {
@@ -1425,53 +1475,34 @@
       "dev": true
     },
     "copy-webpack-plugin": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz",
-      "integrity": "sha512-q5m6Vz4elsuyVEIUXr7wJdIdePWTubsqVbEMvf1WQnHGv0Q+9yPRu7MtYFPt+GBOXRav9lvIINifTQ1vSCs+eA==",
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz",
+      "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==",
       "dev": true,
       "requires": {
-        "cacache": "^15.0.4",
+        "cacache": "^15.0.5",
         "fast-glob": "^3.2.4",
         "find-cache-dir": "^3.3.1",
         "glob-parent": "^5.1.1",
         "globby": "^11.0.1",
         "loader-utils": "^2.0.0",
         "normalize-path": "^3.0.0",
-        "p-limit": "^3.0.1",
-        "schema-utils": "^2.7.0",
-        "serialize-javascript": "^4.0.0",
+        "p-limit": "^3.0.2",
+        "schema-utils": "^3.0.0",
+        "serialize-javascript": "^5.0.1",
         "webpack-sources": "^1.4.3"
       },
       "dependencies": {
-        "cacache": {
-          "version": "15.0.5",
-          "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz",
-          "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==",
-          "dev": true,
-          "requires": {
-            "@npmcli/move-file": "^1.0.1",
-            "chownr": "^2.0.0",
-            "fs-minipass": "^2.0.0",
-            "glob": "^7.1.4",
-            "infer-owner": "^1.0.4",
-            "lru-cache": "^6.0.0",
-            "minipass": "^3.1.1",
-            "minipass-collect": "^1.0.2",
-            "minipass-flush": "^1.0.5",
-            "minipass-pipeline": "^1.2.2",
-            "mkdirp": "^1.0.3",
-            "p-map": "^4.0.0",
-            "promise-inflight": "^1.0.1",
-            "rimraf": "^3.0.2",
-            "ssri": "^8.0.0",
-            "tar": "^6.0.2",
-            "unique-filename": "^1.1.1"
-          }
+        "@types/json-schema": {
+          "version": "7.0.7",
+          "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
+          "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==",
+          "dev": true
         },
-        "chownr": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
-          "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+        "ajv-keywords": {
+          "version": "3.5.2",
+          "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+          "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
           "dev": true
         },
         "emojis-list": {
@@ -1480,40 +1511,10 @@
           "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
           "dev": true
         },
-        "find-cache-dir": {
-          "version": "3.3.1",
-          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
-          "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
-          "dev": true,
-          "requires": {
-            "commondir": "^1.0.1",
-            "make-dir": "^3.0.2",
-            "pkg-dir": "^4.1.0"
-          }
-        },
-        "find-up": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-          "dev": true,
-          "requires": {
-            "locate-path": "^5.0.0",
-            "path-exists": "^4.0.0"
-          }
-        },
-        "glob-parent": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
-          "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
-          "dev": true,
-          "requires": {
-            "is-glob": "^4.0.1"
-          }
-        },
         "json5": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
-          "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+          "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
           "dev": true,
           "requires": {
             "minimist": "^1.2.5"
@@ -1530,143 +1531,41 @@
             "json5": "^2.1.2"
           }
         },
-        "locate-path": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-          "dev": true,
-          "requires": {
-            "p-locate": "^4.1.0"
-          }
-        },
-        "lru-cache": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-          "dev": true,
-          "requires": {
-            "yallist": "^4.0.0"
-          }
-        },
-        "make-dir": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-          "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-          "dev": true,
-          "requires": {
-            "semver": "^6.0.0"
-          }
-        },
-        "mkdirp": {
-          "version": "1.0.4",
-          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
-          "dev": true
-        },
         "p-limit": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz",
-          "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==",
-          "dev": true,
-          "requires": {
-            "p-try": "^2.0.0"
-          }
-        },
-        "p-locate": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-          "dev": true,
-          "requires": {
-            "p-limit": "^2.2.0"
-          },
-          "dependencies": {
-            "p-limit": {
-              "version": "2.3.0",
-              "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-              "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
-              "dev": true,
-              "requires": {
-                "p-try": "^2.0.0"
-              }
-            }
-          }
-        },
-        "path-exists": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-          "dev": true
-        },
-        "pkg-dir": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
-          "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
-          "dev": true,
-          "requires": {
-            "find-up": "^4.0.0"
-          }
-        },
-        "rimraf": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-          "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-          "dev": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        },
-        "semver": {
-          "version": "6.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-          "dev": true
-        },
-        "ssri": {
-          "version": "8.0.0",
-          "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz",
-          "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==",
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+          "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
           "dev": true,
           "requires": {
-            "minipass": "^3.1.1"
+            "yocto-queue": "^0.1.0"
           }
         },
-        "tar": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/tar/-/tar-6.0.2.tgz",
-          "integrity": "sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg==",
+        "schema-utils": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz",
+          "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==",
           "dev": true,
           "requires": {
-            "chownr": "^2.0.0",
-            "fs-minipass": "^2.0.0",
-            "minipass": "^3.0.0",
-            "minizlib": "^2.1.0",
-            "mkdirp": "^1.0.3",
-            "yallist": "^4.0.0"
+            "@types/json-schema": "^7.0.6",
+            "ajv": "^6.12.5",
+            "ajv-keywords": "^3.5.2"
           }
-        },
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
         }
       }
     },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-      "dev": true
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
     "create-ecdh": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
-      "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+      "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
       "dev": true,
       "requires": {
         "bn.js": "^4.1.0",
-        "elliptic": "^6.0.0"
+        "elliptic": "^6.5.3"
       },
       "dependencies": {
         "bn.js": {
@@ -1816,12 +1715,12 @@
       }
     },
     "debug": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+      "version": "4.3.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+      "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
       "dev": true,
       "requires": {
-        "ms": "^2.1.1"
+        "ms": "2.1.2"
       }
     },
     "decamelize": {
@@ -1944,6 +1843,37 @@
       "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
       "dev": true
     },
+    "duplexer2": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
+      "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=",
+      "requires": {
+        "readable-stream": "~1.1.9"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+        },
+        "readable-stream": {
+          "version": "1.1.14",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+          "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "0.0.1",
+            "string_decoder": "~0.10.x"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+        }
+      }
+    },
     "duplexify": {
       "version": "3.7.1",
       "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@@ -1967,24 +1897,24 @@
       }
     },
     "elliptic": {
-      "version": "6.5.3",
-      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
-      "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
+      "version": "6.5.4",
+      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+      "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
       "dev": true,
       "requires": {
-        "bn.js": "^4.4.0",
-        "brorand": "^1.0.1",
+        "bn.js": "^4.11.9",
+        "brorand": "^1.1.0",
         "hash.js": "^1.0.0",
-        "hmac-drbg": "^1.0.0",
-        "inherits": "^2.0.1",
-        "minimalistic-assert": "^1.0.0",
-        "minimalistic-crypto-utils": "^1.0.0"
+        "hmac-drbg": "^1.0.1",
+        "inherits": "^2.0.4",
+        "minimalistic-assert": "^1.0.1",
+        "minimalistic-crypto-utils": "^1.0.1"
       },
       "dependencies": {
         "bn.js": {
-          "version": "4.11.9",
-          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
-          "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+          "version": "4.12.0",
+          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+          "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
           "dev": true
         }
       }
@@ -2010,6 +1940,14 @@
         "once": "^1.4.0"
       }
     },
+    "engine-check": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/engine-check/-/engine-check-1.0.1.tgz",
+      "integrity": "sha512-We1LIiRIkaGfEvhuqgmvyJiZFGO+lpD7nMfSFryM5UaFhrh9vfZWYbb4lqZhsnVCRW55RSflC7WgTiEHbdbIAA==",
+      "requires": {
+        "semver": "^5.0"
+      }
+    },
     "enhanced-resolve": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
@@ -2052,9 +1990,9 @@
       }
     },
     "es6-shim": {
-      "version": "0.35.5",
-      "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.5.tgz",
-      "integrity": "sha512-E9kK/bjtCQRpN1K28Xh4BlmP8egvZBGJJ+9GtnzOwt7mdqtrjHFuVGr7QJfdjBIKqrlU5duPf3pCBoDrkjVYFg=="
+      "version": "0.35.6",
+      "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.6.tgz",
+      "integrity": "sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA=="
     },
     "escape-string-regexp": {
       "version": "1.0.5",
@@ -2072,18 +2010,31 @@
         "estraverse": "^4.1.1"
       }
     },
+    "esm": {
+      "version": "3.2.25",
+      "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
+      "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
+    },
     "esprima": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz",
       "integrity": "sha1-U88kes2ncxPlUcOqLnM0LT+099k="
     },
     "esrecurse": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
-      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
       "dev": true,
       "requires": {
-        "estraverse": "^4.1.0"
+        "estraverse": "^5.2.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+          "dev": true
+        }
       }
     },
     "estraverse": {
@@ -2167,6 +2118,11 @@
         "homedir-polyfill": "^1.0.1"
       }
     },
+    "expected-node-version": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/expected-node-version/-/expected-node-version-1.0.2.tgz",
+      "integrity": "sha1-uNIlub9nap6H4G29YVtS/J0eOGs="
+    },
     "expose-loader": {
       "version": "0.7.5",
       "resolved": "https://registry.npmjs.org/expose-loader/-/expose-loader-0.7.5.tgz",
@@ -2272,15 +2228,15 @@
       "dev": true
     },
     "fast-deep-equal": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
-      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
       "dev": true
     },
     "fast-glob": {
-      "version": "3.2.4",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz",
-      "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==",
+      "version": "3.2.5",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
+      "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
       "dev": true,
       "requires": {
         "@nodelib/fs.stat": "^2.0.2",
@@ -2302,20 +2258,11 @@
         },
         "fill-range": {
           "version": "7.0.1",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-          "dev": true,
-          "requires": {
-            "to-regex-range": "^5.0.1"
-          }
-        },
-        "glob-parent": {
-          "version": "5.1.1",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
-          "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
           "dev": true,
           "requires": {
-            "is-glob": "^4.0.1"
+            "to-regex-range": "^5.0.1"
           }
         },
         "is-number": {
@@ -2352,9 +2299,9 @@
       "dev": true
     },
     "fastq": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz",
-      "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==",
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz",
+      "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==",
       "dev": true,
       "requires": {
         "reusify": "^1.0.4"
@@ -2390,14 +2337,59 @@
       }
     },
     "find-cache-dir": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
-      "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
+      "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==",
       "dev": true,
       "requires": {
         "commondir": "^1.0.1",
-        "make-dir": "^2.0.0",
-        "pkg-dir": "^3.0.0"
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^4.1.0"
+          }
+        },
+        "p-locate": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.2.0"
+          }
+        },
+        "path-exists": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
+        },
+        "pkg-dir": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+          "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+          "dev": true,
+          "requires": {
+            "find-up": "^4.0.0"
+          }
+        }
       }
     },
     "find-up": {
@@ -2501,9 +2493,9 @@
       "dev": true
     },
     "fsevents": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
-      "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz",
+      "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
       "dev": true,
       "optional": true
     },
@@ -2545,9 +2537,9 @@
       }
     },
     "gensync": {
-      "version": "1.0.0-beta.1",
-      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
-      "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
       "dev": true
     },
     "get-caller-file": {
@@ -2592,26 +2584,12 @@
       }
     },
     "glob-parent": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-      "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+      "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
       "dev": true,
-      "optional": true,
       "requires": {
-        "is-glob": "^3.1.0",
-        "path-dirname": "^1.0.0"
-      },
-      "dependencies": {
-        "is-glob": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-          "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "is-extglob": "^2.1.0"
-          }
-        }
+        "is-glob": "^4.0.1"
       }
     },
     "global-modules": {
@@ -2656,9 +2634,9 @@
       "dev": true
     },
     "globby": {
-      "version": "11.0.1",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
-      "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
+      "version": "11.0.2",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
+      "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
       "dev": true,
       "requires": {
         "array-union": "^2.1.0",
@@ -2824,9 +2802,9 @@
       }
     },
     "highlight.js": {
-      "version": "10.4.1",
-      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.1.tgz",
-      "integrity": "sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg=="
+      "version": "10.5.0",
+      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.5.0.tgz",
+      "integrity": "sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw=="
     },
     "hmac-drbg": {
       "version": "1.0.1",
@@ -2876,6 +2854,53 @@
       "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz",
       "integrity": "sha1-GZT/rs3+nEQe0r2sdFK3u0yeQaQ="
     },
+    "hyperquest": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/hyperquest/-/hyperquest-2.1.3.tgz",
+      "integrity": "sha512-fUuDOrB47PqNK/BAMOS13v41UoaqIxqSLHX6CAbOD7OfT+/GCWO1/vPLfTNutOeXrv1ikuaZ3yux+33Z9vh+rw==",
+      "requires": {
+        "buffer-from": "^0.1.1",
+        "duplexer2": "~0.0.2",
+        "through2": "~0.6.3"
+      },
+      "dependencies": {
+        "buffer-from": {
+          "version": "0.1.2",
+          "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
+          "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
+        },
+        "isarray": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+        },
+        "readable-stream": {
+          "version": "1.0.34",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "0.0.1",
+            "string_decoder": "~0.10.x"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+        },
+        "through2": {
+          "version": "0.6.5",
+          "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+          "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+          "requires": {
+            "readable-stream": ">=1.0.33-1 <1.1.0-0",
+            "xtend": ">=4.0.0 <4.1.0-0"
+          }
+        }
+      }
+    },
     "icss-utils": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz",
@@ -2886,9 +2911,9 @@
       }
     },
     "ieee754": {
-      "version": "1.1.13",
-      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
-      "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
       "dev": true
     },
     "iferr": {
@@ -2959,8 +2984,7 @@
     "inherits": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
     "ini": {
       "version": "1.3.8",
@@ -3229,8 +3253,7 @@
     "json-stringify-safe": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
-      "dev": true
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
     },
     "json5": {
       "version": "1.0.1",
@@ -3241,6 +3264,17 @@
         "minimist": "^1.2.0"
       }
     },
+    "jsonist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/jsonist/-/jsonist-2.1.2.tgz",
+      "integrity": "sha512-8yqmWJAC2VaYoSKQAbsfgCpGY5o/1etWzx6ZxaZrC4iGaHrHUZEo+a2MyF8w+2uTavTlHdLWaZUoR19UfBstxQ==",
+      "requires": {
+        "bl": "~3.0.0",
+        "hyperquest": "~2.1.3",
+        "json-stringify-safe": "~5.0.1",
+        "xtend": "~4.0.1"
+      }
+    },
     "jsprim": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -3329,22 +3363,29 @@
       }
     },
     "lru-cache": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
       "dev": true,
       "requires": {
-        "yallist": "^3.0.2"
+        "yallist": "^4.0.0"
       }
     },
     "make-dir": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
-      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
       "dev": true,
       "requires": {
-        "pify": "^4.0.1",
-        "semver": "^5.6.0"
+        "semver": "^6.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
       }
     },
     "map-cache": {
@@ -3468,9 +3509,9 @@
       }
     },
     "mini-css-extract-plugin": {
-      "version": "0.10.0",
-      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.10.0.tgz",
-      "integrity": "sha512-QgKgJBjaJhxVPwrLNqqwNS0AGkuQQ31Hp4xGXEK/P7wehEg6qmNtReHKai3zRXqY60wGVWLYcOMJK2b98aGc3A==",
+      "version": "0.10.1",
+      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.10.1.tgz",
+      "integrity": "sha512-9B10gZixtNjHerADBrMxPXM5G0uL0CRGMcLRV67I8nd1SKbwJrI0okKUzD+PxKsUZ9Dxt8/hPvtzF0DrRnrOyA==",
       "dev": true,
       "requires": {
         "loader-utils": "^1.1.0",
@@ -3519,6 +3560,47 @@
       "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
       "dev": true
     },
+    "minimum-node-version": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/minimum-node-version/-/minimum-node-version-3.0.0.tgz",
+      "integrity": "sha512-XFcX466e9NjEbx2lVyYDaRtWTkB6hPEizIRWkF2D0G80mWYM/YVW+PUibsFjuvnpNYlpKzjdupFXJHEsK3w8Jg==",
+      "requires": {
+        "engine-check": "^1.0.1",
+        "esm": "^3.2.25",
+        "expected-node-version": "^1.0.2",
+        "node-version-data": "^1.0.1",
+        "pify": "^5.0.0",
+        "semver": "^7.3.4"
+      },
+      "dependencies": {
+        "lru-cache": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+          "requires": {
+            "yallist": "^4.0.0"
+          }
+        },
+        "pify": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz",
+          "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA=="
+        },
+        "semver": {
+          "version": "7.3.4",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+          "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+          "requires": {
+            "lru-cache": "^6.0.0"
+          }
+        },
+        "yallist": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+        }
+      }
+    },
     "minipass": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
@@ -3526,14 +3608,6 @@
       "dev": true,
       "requires": {
         "yallist": "^4.0.0"
-      },
-      "dependencies": {
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
-        }
       }
     },
     "minipass-collect": {
@@ -3564,21 +3638,13 @@
       }
     },
     "minizlib": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.0.tgz",
-      "integrity": "sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+      "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
       "dev": true,
       "requires": {
         "minipass": "^3.0.0",
         "yallist": "^4.0.0"
-      },
-      "dependencies": {
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
-        }
       }
     },
     "mississippi": {
@@ -3675,9 +3741,9 @@
       }
     },
     "neo-async": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
-      "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
       "dev": true
     },
     "nice-try": {
@@ -3805,6 +3871,23 @@
         }
       }
     },
+    "node-version-data": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/node-version-data/-/node-version-data-1.1.0.tgz",
+      "integrity": "sha512-/uQsoJ6Q5JvReqSlHaWazlVdtJYm/1VXk2eaIvN1Z0C7gD8RGirlIdWvNs3OqgmltkM1toV+9R+drhV4fqifJw==",
+      "requires": {
+        "after": "~0.8.2",
+        "jsonist": "~2.1.2",
+        "semver": "~6.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+        }
+      }
+    },
     "nopt": {
       "version": "3.0.6",
       "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@@ -4027,14 +4110,13 @@
       }
     },
     "parse-asn1": {
-      "version": "5.1.5",
-      "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
-      "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+      "version": "5.1.6",
+      "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
+      "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
       "dev": true,
       "requires": {
-        "asn1.js": "^4.0.0",
+        "asn1.js": "^5.2.0",
         "browserify-aes": "^1.0.0",
-        "create-hash": "^1.1.0",
         "evp_bytestokey": "^1.0.0",
         "pbkdf2": "^3.0.3",
         "safe-buffer": "^5.1.1"
@@ -4355,9 +4437,9 @@
       "dev": true
     },
     "purecss": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/purecss/-/purecss-2.0.3.tgz",
-      "integrity": "sha512-jK5t8Wdyh1xiskKt9Pk3psruRP7XHcHYfsBkA9tu+CGGxaC3goTyd9EFCFyYuhC7AK/68NqDfuOsP8FgQ9vHRg=="
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/purecss/-/purecss-2.0.5.tgz",
+      "integrity": "sha512-T9yg6NwJf1fgjUs+Vo0cEhHAR7lnkYbqhNYGdKzL9KjZ0ZECvvYZ2pgvOTN3jDa+1mpouMFaskuffG+lOADwxQ=="
     },
     "qs": {
       "version": "6.5.2",
@@ -4483,9 +4565,9 @@
       }
     },
     "readdirp": {
-      "version": "3.4.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
-      "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+      "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
       "dev": true,
       "optional": true,
       "requires": {
@@ -4678,9 +4760,9 @@
       }
     },
     "run-parallel": {
-      "version": "1.1.9",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz",
-      "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
+      "version": "1.1.10",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz",
+      "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==",
       "dev": true
     },
     "run-queue": {
@@ -4695,8 +4777,7 @@
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "dev": true
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
     },
     "safe-regex": {
       "version": "1.1.0",
@@ -4854,13 +4935,12 @@
     "semver": {
       "version": "5.7.1",
       "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-      "dev": true
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
     },
     "serialize-javascript": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
-      "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
+      "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
       "dev": true,
       "requires": {
         "randombytes": "^2.1.0"
@@ -5189,12 +5269,12 @@
       }
     },
     "ssri": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
-      "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
+      "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
       "dev": true,
       "requires": {
-        "figgy-pudding": "^3.5.1"
+        "minipass": "^3.1.1"
       }
     },
     "static-extend": {
@@ -5287,7 +5367,6 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
       "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dev": true,
       "requires": {
         "safe-buffer": "~5.1.0"
       }
@@ -5320,23 +5399,39 @@
       }
     },
     "style-loader": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.0.1.tgz",
-      "integrity": "sha512-CnpEkSR1C+REjudiTWCv4+ssP7SCiuaQZJTZDWBRwTJoS90mdqkB8uOGMHKgVeUzpaU7IfLWoyQbvvs5Joj3Xw==",
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz",
+      "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==",
       "dev": true,
       "requires": {
-        "loader-utils": "^1.2.3",
-        "schema-utils": "^2.0.1"
+        "loader-utils": "^2.0.0",
+        "schema-utils": "^2.7.0"
       },
       "dependencies": {
-        "schema-utils": {
-          "version": "2.6.1",
-          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.1.tgz",
-          "integrity": "sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg==",
+        "emojis-list": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+          "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+          "dev": true
+        },
+        "json5": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+          "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        },
+        "loader-utils": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
           "dev": true,
           "requires": {
-            "ajv": "^6.10.2",
-            "ajv-keywords": "^3.4.1"
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
           }
         }
       }
@@ -5387,22 +5482,81 @@
       }
     },
     "terser-webpack-plugin": {
-      "version": "1.4.4",
-      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz",
-      "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==",
+      "version": "1.4.5",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
+      "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
       "dev": true,
       "requires": {
         "cacache": "^12.0.2",
         "find-cache-dir": "^2.1.0",
         "is-wsl": "^1.1.0",
         "schema-utils": "^1.0.0",
-        "serialize-javascript": "^3.1.0",
+        "serialize-javascript": "^4.0.0",
         "source-map": "^0.6.1",
         "terser": "^4.1.2",
         "webpack-sources": "^1.4.0",
         "worker-farm": "^1.7.0"
       },
       "dependencies": {
+        "cacache": {
+          "version": "12.0.4",
+          "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+          "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+          "dev": true,
+          "requires": {
+            "bluebird": "^3.5.5",
+            "chownr": "^1.1.1",
+            "figgy-pudding": "^3.5.1",
+            "glob": "^7.1.4",
+            "graceful-fs": "^4.1.15",
+            "infer-owner": "^1.0.3",
+            "lru-cache": "^5.1.1",
+            "mississippi": "^3.0.0",
+            "mkdirp": "^0.5.1",
+            "move-concurrently": "^1.0.1",
+            "promise-inflight": "^1.0.1",
+            "rimraf": "^2.6.3",
+            "ssri": "^6.0.1",
+            "unique-filename": "^1.1.1",
+            "y18n": "^4.0.0"
+          }
+        },
+        "chownr": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+          "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+          "dev": true
+        },
+        "find-cache-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+          "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+          "dev": true,
+          "requires": {
+            "commondir": "^1.0.1",
+            "make-dir": "^2.0.0",
+            "pkg-dir": "^3.0.0"
+          }
+        },
+        "lru-cache": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+          "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+          "dev": true,
+          "requires": {
+            "yallist": "^3.0.2"
+          }
+        },
+        "make-dir": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+          "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+          "dev": true,
+          "requires": {
+            "pify": "^4.0.1",
+            "semver": "^5.6.0"
+          }
+        },
         "schema-utils": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -5415,9 +5569,9 @@
           }
         },
         "serialize-javascript": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
-          "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
+          "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
           "dev": true,
           "requires": {
             "randombytes": "^2.1.0"
@@ -5428,6 +5582,21 @@
           "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
           "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
           "dev": true
+        },
+        "ssri": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+          "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+          "dev": true,
+          "requires": {
+            "figgy-pudding": "^3.5.1"
+          }
+        },
+        "yallist": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+          "dev": true
         }
       }
     },
@@ -5442,9 +5611,9 @@
       }
     },
     "timers-browserify": {
-      "version": "2.0.11",
-      "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
-      "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==",
+      "version": "2.0.12",
+      "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",
+      "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==",
       "dev": true,
       "requires": {
         "setimmediate": "^1.0.4"
@@ -5535,9 +5704,9 @@
       }
     },
     "tslib": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
-      "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
       "dev": true
     },
     "tty-browserify": {
@@ -5709,8 +5878,7 @@
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
-      "dev": true
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
     },
     "uuid": {
       "version": "3.3.3",
@@ -5752,21 +5920,21 @@
       "dev": true
     },
     "watchpack": {
-      "version": "1.7.4",
-      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",
-      "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==",
+      "version": "1.7.5",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
+      "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
       "dev": true,
       "requires": {
         "chokidar": "^3.4.1",
         "graceful-fs": "^4.1.2",
         "neo-async": "^2.5.0",
-        "watchpack-chokidar2": "^2.0.0"
+        "watchpack-chokidar2": "^2.0.1"
       }
     },
     "watchpack-chokidar2": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz",
-      "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz",
+      "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==",
       "dev": true,
       "optional": true,
       "requires": {
@@ -5834,6 +6002,29 @@
             "nan": "^2.12.1"
           }
         },
+        "glob-parent": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+          "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "is-glob": "^3.1.0",
+            "path-dirname": "^1.0.0"
+          },
+          "dependencies": {
+            "is-glob": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+              "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "is-extglob": "^2.1.0"
+              }
+            }
+          }
+        },
         "is-binary-path": {
           "version": "1.0.1",
           "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
@@ -5859,9 +6050,9 @@
       }
     },
     "webpack": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz",
-      "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==",
+      "version": "4.46.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz",
+      "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==",
       "dev": true,
       "requires": {
         "@webassemblyjs/ast": "1.9.0",
@@ -5872,7 +6063,7 @@
         "ajv": "^6.10.2",
         "ajv-keywords": "^3.4.1",
         "chrome-trace-event": "^1.0.2",
-        "enhanced-resolve": "^4.3.0",
+        "enhanced-resolve": "^4.5.0",
         "eslint-scope": "^4.0.3",
         "json-parse-better-errors": "^1.0.2",
         "loader-runner": "^2.4.0",
@@ -5889,6 +6080,29 @@
         "webpack-sources": "^1.4.1"
       },
       "dependencies": {
+        "enhanced-resolve": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
+          "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "memory-fs": "^0.5.0",
+            "tapable": "^1.0.0"
+          },
+          "dependencies": {
+            "memory-fs": {
+              "version": "0.5.0",
+              "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
+              "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
+              "dev": true,
+              "requires": {
+                "errno": "^0.1.3",
+                "readable-stream": "^2.0.1"
+              }
+            }
+          }
+        },
         "schema-utils": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -6172,8 +6386,7 @@
     "xtend": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
-      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
-      "dev": true
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
     },
     "y18n": {
       "version": "4.0.0",
@@ -6182,9 +6395,9 @@
       "dev": true
     },
     "yallist": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
       "dev": true
     },
     "yargs": {
@@ -6248,6 +6461,12 @@
         "camelcase": "^5.0.0",
         "decamelize": "^1.2.0"
       }
+    },
+    "yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true
     }
   }
 }
diff --git a/package.json b/package.json
index fa91590d7b7287a7f5a78897f1b8b744d3f040f6..c1155a3d8ebe6a86929ca262a7f10f402b0f4905 100644
--- a/package.json
+++ b/package.json
@@ -4,32 +4,38 @@
   "repository": "https://github.com/simplesamlphp/simplesamlphp",
   "author": "olimpiam",
   "license": "MIT",
+  "engines": {
+    "node": ">=10.0.0",
+    "npm": ">=6.0.0"
+  },
   "scripts": {
+    "post-intall": "minimum-node-version",
     "clean": "rm -rf www/assets/css/* && rm -rf www/assets/js/*",
     "build": "webpack -p"
   },
   "dependencies": {
+    "@fortawesome/fontawesome-free": "^5.15.2",
     "clipboard": "^2.0.6",
-    "es6-shim": "^0.35.5",
-    "@fortawesome/fontawesome-free": "^5.14.0",
-    "highlight.js": "^10.4.1",
+    "es6-shim": "^0.35.6",
+    "highlight.js": "^10.5.0",
     "jquery": "^3.5.1",
     "jquery-ui": "^1.12.1",
-    "purecss": "^2.0.3",
+    "minimum-node-version": "^3.0.0",
+    "purecss": "^2.0.5",
     "reset-css": "^5.0.1",
     "selectize": "^0.12.6"
   },
   "devDependencies": {
-    "@babel/core": "^7.11.0",
-    "babel-loader": "^8.1.0",
-    "copy-webpack-plugin": "^6.0.3",
+    "@babel/core": "^7.12.10",
+    "babel-loader": "^8.2.2",
+    "copy-webpack-plugin": "^6.4.1",
     "css-loader": "^3.6.0",
     "expose-loader": "^0.7.5",
-    "mini-css-extract-plugin": "^0.10.0",
+    "mini-css-extract-plugin": "^0.10.1",
     "node-sass": "^4.14.1",
     "sass-loader": "^9.0.3",
-    "style-loader": "^1.0.1",
-    "webpack": "^4.44.1",
+    "style-loader": "^1.3.0",
+    "webpack": "^4.46.0",
     "webpack-cli": "^3.3.12"
   }
 }
diff --git a/phpunit.xml b/phpunit.xml
index 65c86c13f9a10dfc4d33ee9c72c5dfb1db509ba5..ff697d42f4f83fa4eb91d929c2e9c3a71f00e8d4 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -2,17 +2,16 @@
 <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" bootstrap="./tests/bootstrap.php" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
   <coverage processUncoveredFiles="true">
     <include>
-      <directory suffix=".php">./lib/</directory>
-      <directory suffix=".php">./modules/admin/lib/</directory>
-      <directory suffix=".php">./modules/core/lib/</directory>
-      <directory suffix=".php">./modules/cron/lib/</directory>
-      <directory suffix=".php">./modules/exampleauth/lib/</directory>
-      <directory suffix=".php">./modules/multiauth/lib/</directory>
-      <directory suffix=".php">./modules/saml/lib/</directory>
+      <directory suffix=".php">./lib</directory>
+      <directory suffix=".php">./modules/admin/lib</directory>
+      <directory suffix=".php">./modules/core/lib</directory>
+      <directory suffix=".php">./modules/cron/lib</directory>
+      <directory suffix=".php">./modules/exampleauth/lib</directory>
+      <directory suffix=".php">./modules/multiauth/lib</directory>
+      <directory suffix=".php">./modules/saml/lib</directory>
     </include>
     <exclude>
-      <directory>./vendor/</directory>
-      <directory>./tests/</directory>
+      <directory>./tests</directory>
       <file>./lib/SimpleSAML/Utils/HttpAdapter.php</file>
     </exclude>
     <report>
diff --git a/psalm.xml b/psalm.xml
index 85eaf8882d1a266254852bcbf47dcf19602e7047..6f229cf1ad8c607dd7542b9476460d90ac6605a2 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -12,6 +12,7 @@
         <directory name="metadata-templates" />
         <directory name="modules" />
         <directory name="tests" />
+        <directory name="www" />
 
         <!-- Ignore certain directories -->
         <ignoreFiles>
@@ -84,6 +85,13 @@
                 <directory name="tests" />
             </errorLevel>
         </InternalMethod>
+
+        <!-- Suppress Psalm-issue - We should be able to fix this with the static return-type in PHP 8.0 -->
+        <UnsafeInstantiation>
+            <errorLevel type="suppress">
+                <directory name="tests" />
+            </errorLevel>
+        </UnsafeInstantiation>
     </issueHandlers>
 
     <stubs>
diff --git a/tests/SigningTestCase.php b/tests/SigningTestCase.php
index b5ee39435f6b5515a8a295f12fe3b71f7be25b6e..2ab9443eb94df50b6ec07ba40943f18bae82fd9e 100644
--- a/tests/SigningTestCase.php
+++ b/tests/SigningTestCase.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace SimpleSAML\Test;
 
 use org\bovigo\vfs\vfsStream;
+use org\bovigo\vfs\vfsStreamDirectory;
 use PHPUnit\Framework\TestCase;
 use ReflectionClass;
 use SimpleSAML\Configuration;
@@ -19,7 +20,7 @@ class SigningTestCase extends TestCase
 {
     // openssl genrsa -out ca.key.pem 2048
     /** @var string $ca_private_key */
-    protected $ca_private_key = <<<'NOWDOC'
+    protected string $ca_private_key = <<<'NOWDOC'
 -----BEGIN RSA PRIVATE KEY-----
 MIIEpQIBAAKCAQEAtj5GuvnC5aCg8bhq2Yy4isp/uXtRRWKhbB5aYP7/1DwwwQ1Z
 LtBosBAA5SMD4s4L9w/bbJVVVAzhc9cpe2vDYLe1faUZlvOzJv/JuH/ux5NRkgmx
@@ -51,7 +52,7 @@ NOWDOC;
 
     // openssl req -key ca.key.pem -new -x509 -days 3650 -out ca.cert.pem
     /** @var string $ca_certificate */
-    private $ca_certificate = <<<'NOWDOC'
+    private string $ca_certificate = <<<'NOWDOC'
 -----BEGIN CERTIFICATE-----
 MIIDtjCCAp6gAwIBAgIJAII4rW68Q+IsMA0GCSqGSIb3DQEBCwUAMHAxCzAJBgNV
 BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
@@ -78,7 +79,7 @@ NOWDOC;
 
     // openssl genrsa -out good.key.pem 2048
     /** @var string $good_private_key */
-    protected $good_private_key = <<<'NOWDOC'
+    protected string $good_private_key = <<<'NOWDOC'
 -----BEGIN RSA PRIVATE KEY-----
 MIIEowIBAAKCAQEAqmNn4bt/jrMHgoWtwXLc2ok17BHh1O5ETbn9rK3KFjk3BXp5
 3aGveill+KbW7SgriGZSa1KBE2uaQy2mZpiBQqFrLcgKhtzaCNLyBvKOozQhn/XN
@@ -118,7 +119,7 @@ NOWDOC;
     //      -in good.csr.pem \
     //      -out good.cert.pem
     /** @var string $good_certificate */
-    protected $good_certificate = <<<'NOWDOC'
+    protected string $good_certificate = <<<'NOWDOC'
 -----BEGIN CERTIFICATE-----
 MIIDZTCCAk0CCQC+sxqJmyko6TANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJB
 VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
@@ -143,28 +144,28 @@ hQc0xnrLQ255SjMn+nQtMkVSuKwAUqaAP1ByyiVbN1cBlHnMiJCjvBI58bSTdlVK
 NOWDOC;
 
     /** @var string */
-    protected $good_private_key_file;
+    protected string $good_private_key_file;
 
     /** @var string */
-    protected $good_certificate_file;
+    protected string $good_certificate_file;
 
     /** @var string */
-    protected $certdir;
+    protected string $certdir;
 
     /** @var \org\bovigo\vfs\vfsStreamDirectory */
-    protected $root;
+    protected VfsStreamDirectory $root;
 
     /** @var string */
-    protected $root_directory;
+    protected string $root_directory;
 
     /** @var string */
-    protected $ca_private_key_file;
+    protected string $ca_private_key_file;
 
     /** @var string */
-    protected $ca_certificate_file;
+    protected string $ca_certificate_file;
 
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     protected const ROOTDIRNAME = 'testdir';
     protected const DEFAULTCERTDIR = 'certdir';
diff --git a/tests/Utils/ClearStateTestCase.php b/tests/Utils/ClearStateTestCase.php
index d82c423b805a74f498d637a3c2e35090018a9168..644e4353f8e287e94d221df0fd949fe6872474f6 100644
--- a/tests/Utils/ClearStateTestCase.php
+++ b/tests/Utils/ClearStateTestCase.php
@@ -13,16 +13,16 @@ class ClearStateTestCase extends TestCase
 {
     /**
      * Used for managing and clearing state
-     * @var StateClearer
+     * @var \SimpleSAML\Test\Utils\StateClearer|null
      */
-    protected static $stateClearer;
+    protected static ?StateClearer $stateClearer = null;
 
 
     /**
      */
     public static function setUpBeforeClass(): void
     {
-        if (!self::$stateClearer) {
+        if (self::$stateClearer === null) {
             self::$stateClearer = new StateClearer();
             self::$stateClearer->backupGlobals();
         }
diff --git a/tests/Utils/ExitTestException.php b/tests/Utils/ExitTestException.php
index dc64a0ae842e4814511222ae022ef117e4ae38e9..c981fb1cd455ce72e62b7fd98b9aad77f907b691 100644
--- a/tests/Utils/ExitTestException.php
+++ b/tests/Utils/ExitTestException.php
@@ -10,7 +10,7 @@ namespace SimpleSAML\Test\Utils;
 class ExitTestException extends \Exception
 {
     /** @var array */
-    private $testResult;
+    private array $testResult;
 
 
     /**
diff --git a/tests/Utils/StateClearer.php b/tests/Utils/StateClearer.php
index 05e69814d0365ebcdea0a751cc0e1886a28995ed..0a9147168c1fd88453fc4b58c930c2c8bb207c0f 100644
--- a/tests/Utils/StateClearer.php
+++ b/tests/Utils/StateClearer.php
@@ -13,13 +13,13 @@ class StateClearer
      * Global state to restore between test runs
      * @var array
      */
-    private $backups = [];
+    private array $backups = [];
 
     /**
      * Class that implement \SimpleSAML\Utils\ClearableState and should have clearInternalState called between tests
      * @var array
      */
-    private $clearableState = [
+    private array $clearableState = [
         'SimpleSAML\Configuration',
         'SimpleSAML\Metadata\MetaDataStorageHandler',
         'SimpleSAML\Store',
@@ -28,9 +28,9 @@ class StateClearer
 
     /**
      * Environmental variables to unset
-     * @var array
+     * @var string[]
      */
-    private $vars_to_unset = ['SIMPLESAMLPHP_CONFIG_DIR'];
+    private array $vars_to_unset = ['SIMPLESAMLPHP_CONFIG_DIR'];
 
 
     /**
diff --git a/tests/lib/SimpleSAML/SessionHandlerPHPTest.php b/tests/lib/SimpleSAML/SessionHandlerPHPTest.php
index 15a82c3817a52dc64b111e30b77c3365217b7f93..5e79591eac60d8f4ee62b915d080a77b2c128d5d 100644
--- a/tests/lib/SimpleSAML/SessionHandlerPHPTest.php
+++ b/tests/lib/SimpleSAML/SessionHandlerPHPTest.php
@@ -15,7 +15,7 @@ use SimpleSAML\Configuration;
 class SessionHandlerPHPTest extends ClearStateTestCase
 {
     /** @var array */
-    protected $sessionConfig = [
+    protected array $sessionConfig = [
         'session.cookie.name' => 'SimpleSAMLSessionID',
         'session.cookie.lifetime' => 100,
         'session.cookie.path' => '/ourPath',
@@ -25,7 +25,7 @@ class SessionHandlerPHPTest extends ClearStateTestCase
     ];
 
     /** @var array */
-    protected $original;
+    protected array $original;
 
 
     /**
diff --git a/tests/lib/SimpleSAML/SessionTest.php b/tests/lib/SimpleSAML/SessionTest.php
index 6c9326b80be5ede926cae0173fd375a37b5cc810..1a75ba4388c9343436bae3b032b03e5493400c1e 100644
--- a/tests/lib/SimpleSAML/SessionTest.php
+++ b/tests/lib/SimpleSAML/SessionTest.php
@@ -15,7 +15,7 @@ use SimpleSAML\Configuration;
 class SessionTest extends ClearStateTestCase
 {
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
     /**
      */
diff --git a/tests/lib/SimpleSAML/Store/RedisTest.php b/tests/lib/SimpleSAML/Store/RedisTest.php
index 069c2435a2760a49da43bb85da0065693e789cbf..9625027c6a11ed8e6bcdf9e37265768a2b38a25f 100644
--- a/tests/lib/SimpleSAML/Store/RedisTest.php
+++ b/tests/lib/SimpleSAML/Store/RedisTest.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace SimpleSAML\Test\Store;
 
 use PHPUnit\Framework\TestCase;
+use PHPUnit\Framework\MockObject\MockObject;
 use Predis\Client;
 use ReflectionClass;
 use SimpleSAML\Configuration;
@@ -22,13 +23,13 @@ use SimpleSAML\Store;
 class RedisTest extends TestCase
 {
     /** @var \PHPUnit\Framework\MockObject\MockObject */
-    protected $mocked_redis;
+    protected MockObject $mocked_redis;
 
     /** @var \SimpleSAML\Store\Redis */
-    protected $redis;
+    protected Store\Redis $redis;
 
     /** @var array */
-    protected $config;
+    protected array $config;
 
 
     /**
@@ -228,7 +229,11 @@ class RedisTest extends TestCase
         $reflectedClass = new ReflectionClass($className);
         $reflectedInstance = $reflectedClass->getProperty('instance');
         $reflectedInstance->setAccessible(true);
-        $reflectedInstance->setValue($service, null);
+        if ($service instanceof Configuration) {
+            $reflectedInstance->setValue($service, []);
+        } else {
+            $reflectedInstance->setValue($service, null);
+        }
         $reflectedInstance->setAccessible(false);
     }
 }
diff --git a/tests/lib/SimpleSAML/Store/SQLTest.php b/tests/lib/SimpleSAML/Store/SQLTest.php
index 28b23d6f4950d6bbc0ce5ea8bee4e62ef7a08111..14358f87f29af74bba2c91e6ff884fd90955c03c 100644
--- a/tests/lib/SimpleSAML/Store/SQLTest.php
+++ b/tests/lib/SimpleSAML/Store/SQLTest.php
@@ -188,7 +188,11 @@ class SQLTest extends TestCase
         $reflectedClass = new ReflectionClass($className);
         $reflectedInstance = $reflectedClass->getProperty('instance');
         $reflectedInstance->setAccessible(true);
-        $reflectedInstance->setValue($service, null);
+        if ($service instanceof Configuration) {
+            $reflectedInstance->setValue($service, []);
+        } else {
+            $reflectedInstance->setValue($service, null);
+        }
         $reflectedInstance->setAccessible(false);
     }
 }
diff --git a/tests/lib/SimpleSAML/StoreTest.php b/tests/lib/SimpleSAML/StoreTest.php
index ffeeb30e3b7cb436c2713d5b0722c97b4a996323..8f278eb6e008c519ea35ff33d5270410316c208d 100644
--- a/tests/lib/SimpleSAML/StoreTest.php
+++ b/tests/lib/SimpleSAML/StoreTest.php
@@ -137,7 +137,11 @@ class StoreTest extends TestCase
         $reflectedClass = new ReflectionClass($className);
         $reflectedInstance = $reflectedClass->getProperty('instance');
         $reflectedInstance->setAccessible(true);
-        $reflectedInstance->setValue($service, null);
+        if ($service instanceof Configuration) {
+            $reflectedInstance->setValue($service, []);
+        } else {
+            $reflectedInstance->setValue($service, null);
+        }
         $reflectedInstance->setAccessible(false);
     }
 }
diff --git a/tests/lib/SimpleSAML/Utils/CryptoTest.php b/tests/lib/SimpleSAML/Utils/CryptoTest.php
index 90b2f71cf0445b080434473f39e152c5b02bf7d1..fa06c98ecc5273667c39d4753645ea22302bde41 100644
--- a/tests/lib/SimpleSAML/Utils/CryptoTest.php
+++ b/tests/lib/SimpleSAML/Utils/CryptoTest.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace SimpleSAML\Test\Utils;
 
 use org\bovigo\vfs\vfsStream;
+use org\bovigo\vfs\vfsStreamDirectory;
 use PHPUnit\Framework\TestCase;
 use ReflectionMethod;
 use SimpleSAML\Configuration;
@@ -23,13 +24,13 @@ class CryptoTest extends TestCase
     private const DEFAULTCERTDIR = 'certdir';
 
     /** @var \org\bovigo\vfs\vfsStreamDirectory */
-    protected $root;
+    protected VfsStreamDirectory $root;
 
     /** @var string */
-    protected $root_directory;
+    protected string $root_directory;
 
     /** @var string */
-    protected $certdir;
+    protected string $certdir;
 
 
     /**
diff --git a/tests/lib/SimpleSAML/Utils/SystemTest.php b/tests/lib/SimpleSAML/Utils/SystemTest.php
index dd233f78921c6d9affb4af92944a0d9a11037770..493ceb94a3b813cb278044ca67d8656d0e3d282f 100644
--- a/tests/lib/SimpleSAML/Utils/SystemTest.php
+++ b/tests/lib/SimpleSAML/Utils/SystemTest.php
@@ -6,6 +6,7 @@ namespace SimpleSAML\Test\Utils;
 
 use InvalidArgumentException;
 use org\bovigo\vfs\vfsStream;
+use org\bovigo\vfs\vfsStreamDirectory;
 use PHPUnit\Framework\TestCase;
 use ReflectionClass;
 use SimpleSAML\Configuration;
@@ -24,9 +25,9 @@ class SystemTest extends TestCase
     private const DEFAULTTEMPDIR = 'tempdir';
 
     /** @var \org\bovigo\vfs\vfsStreamDirectory */
-    protected $root;
+    protected VfsStreamDirectory $root;
 
-    /** @var string */
+    /** @var string string */
     protected $root_directory;
 
 
@@ -284,7 +285,7 @@ class SystemTest extends TestCase
         $reflectedClass = new ReflectionClass($className);
         $reflectedInstance = $reflectedClass->getProperty('instance');
         $reflectedInstance->setAccessible(true);
-        $reflectedInstance->setValue($service, null);
+        $reflectedInstance->setValue($service, []);
         $reflectedInstance->setAccessible(false);
     }
 }
diff --git a/tests/lib/SimpleSAML/XML/ParserTest.php b/tests/lib/SimpleSAML/XML/ParserTest.php
index 1955d4f0f918afa8ffdcddc598273d47159aca77..077117ee40996e7b6f7661292a0d3d4f2cd879bb 100644
--- a/tests/lib/SimpleSAML/XML/ParserTest.php
+++ b/tests/lib/SimpleSAML/XML/ParserTest.php
@@ -27,8 +27,8 @@ class ParserTest extends TestCase
 </Root>
 XML;
 
-    /** @var Parser */
-    private $xml;
+    /** @var \SimpleSAML\XML\Parser */
+    private Parser $xml;
 
 
     /**
diff --git a/tests/lib/SimpleSAML/XML/SignerTest.php b/tests/lib/SimpleSAML/XML/SignerTest.php
index 0713f77e9bb202b6448b214ffcb1b318ae4ba9c2..c53a47795bc56fef69143e5b2b3d031edbe7695c 100644
--- a/tests/lib/SimpleSAML/XML/SignerTest.php
+++ b/tests/lib/SimpleSAML/XML/SignerTest.php
@@ -22,11 +22,11 @@ use SimpleSAML\XML\Signer;
 class SignerTest extends SigningTestCase
 {
     /** @var string */
-    private $other_certificate_file;
+    private string $other_certificate_file;
 
     // openssl req -new -x509 -key good.key.pem -out public2.pem -days 3650
     /** @var string */
-    private $other_certificate = <<<'NOWDOC'
+    private string $other_certificate = <<<'NOWDOC'
 -----BEGIN CERTIFICATE-----
 MIIDazCCAlOgAwIBAgIUGPKUWW1GN07xxAsGENQ+rZPyABAwDQYJKoZIhvcNAQEL
 BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
diff --git a/tests/modules/admin/lib/Controller/ConfigTest.php b/tests/modules/admin/lib/Controller/ConfigTest.php
index 097d9bc43383c09278626a158e1f8b3d16271f74..e7e513dca95b52b5ef757a6cf85d964d63064c38 100644
--- a/tests/modules/admin/lib/Controller/ConfigTest.php
+++ b/tests/modules/admin/lib/Controller/ConfigTest.php
@@ -22,13 +22,13 @@ use Symfony\Component\HttpFoundation\Response;
 class ConfigTest extends TestCase
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Utils\Auth */
-    protected $authUtils;
+    protected Utils\Auth $authUtils;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
diff --git a/tests/modules/admin/lib/Controller/FederationTest.php b/tests/modules/admin/lib/Controller/FederationTest.php
index 54f161fd436d930765f6498901f7cba81caa1e4c..f15cb033c92c1d48b00b6eb9f9fb83b5789f7e4f 100644
--- a/tests/modules/admin/lib/Controller/FederationTest.php
+++ b/tests/modules/admin/lib/Controller/FederationTest.php
@@ -42,22 +42,22 @@ class FederationTest extends TestCase
     public const CERT_PUBLIC = '../' . self::SECURITY . '/certificates/rsa-pem/selfsigned.simplesamlphp.org.crt';
 
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Utils\Auth */
-    protected $authUtils;
+    protected Utils\Auth $authUtils;
 
     /** @var string */
-    private $metadata_xml = self::LIBRARY . '/xml/metadata/valid-metadata-selfsigned.xml';
+    private string $metadata_xml = self::LIBRARY . '/xml/metadata/valid-metadata-selfsigned.xml';
 
     /** @var string */
-    private $broken_metadata_xml = self::LIBRARY . '/xml/metadata/corrupted-metadata-selfsigned.xml';
+    private string $broken_metadata_xml = self::LIBRARY . '/xml/metadata/corrupted-metadata-selfsigned.xml';
 
     /** @var string */
-    private $expired_metadata_xml = self::LIBRARY . '/xml/metadata/expired-metadata.xml';
+    private string $expired_metadata_xml = self::LIBRARY . '/xml/metadata/expired-metadata.xml';
 
     /** @var string */
-    private $ssp_metadata = self::FRAMEWORK . '/metadata/simplesamlphp/saml20-idp-remote_cert_selfsigned.php';
+    private string $ssp_metadata = self::FRAMEWORK . '/metadata/simplesamlphp/saml20-idp-remote_cert_selfsigned.php';
 
     /**
      * Set up for each test.
diff --git a/tests/modules/admin/lib/Controller/TestTest.php b/tests/modules/admin/lib/Controller/TestTest.php
index 72a887eaaf50004af4a6814585071c7383b5e6cb..78743f128572c4cd039645395dcc83aa6a14bb5a 100644
--- a/tests/modules/admin/lib/Controller/TestTest.php
+++ b/tests/modules/admin/lib/Controller/TestTest.php
@@ -10,7 +10,7 @@ use SimpleSAML\Auth;
 use SimpleSAML\Configuration;
 use SimpleSAML\Error;
 use SimpleSAML\HTTP\RunnableResponse;
-use SimpleSAML\Module\admin\Controller;
+use SimpleSAML\Module\admin\Controller\Test as TestController;
 use SimpleSAML\Session;
 use SimpleSAML\Utils;
 use SimpleSAML\XHTML\Template;
@@ -26,13 +26,13 @@ use Symfony\Component\HttpFoundation\Response;
 class TestTest extends TestCase
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Utils\Auth */
-    protected $authUtils;
+    protected Utils\Auth $authUtils;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
@@ -83,7 +83,7 @@ class TestTest extends TestCase
             'GET'
         );
 
-        $c = new Controller\Test($this->config, $this->session);
+        $c = new TestController($this->config, $this->session);
         $c->setAuthUtils($this->authUtils);
         $response = $c->main($request);
 
@@ -103,7 +103,7 @@ class TestTest extends TestCase
             ['logout' => 'notnull']
         );
 
-        $c = new Controller\Test($this->config, $this->session);
+        $c = new TestController($this->config, $this->session);
         $c->setAuthUtils($this->authUtils);
         $c->setAuthSimple(new class ('admin') extends Auth\Simple {
             public function logout($params = null): void
@@ -130,7 +130,7 @@ class TestTest extends TestCase
             [Auth\State::EXCEPTION_PARAM => 'someException']
         );
 
-        $c = new Controller\Test($this->config, $this->session);
+        $c = new TestController($this->config, $this->session);
         $c->setAuthUtils($this->authUtils);
         $c->setAuthState(new class () extends Auth\State {
             public static function loadExceptionState(?string $id = null): ?array
@@ -156,7 +156,7 @@ class TestTest extends TestCase
             ['as' => 'admin']
         );
 
-        $c = new Controller\Test($this->config, $this->session);
+        $c = new TestController($this->config, $this->session);
         $c->setAuthUtils($this->authUtils);
         $c->setAuthSimple(new class ('admin') extends Auth\Simple {
             public function isAuthenticated(): bool
@@ -187,7 +187,7 @@ class TestTest extends TestCase
             'GET'
         );
 
-        $c = new Controller\Test($this->config, $this->session);
+        $c = new TestController($this->config, $this->session);
         $c->setAuthUtils($this->authUtils);
         $c->setAuthSimple(new class ('admin') extends Auth\Simple {
             public function isAuthenticated(): bool
diff --git a/tests/modules/core/lib/Auth/Process/AttributeLimitTest.php b/tests/modules/core/lib/Auth/Process/AttributeLimitTest.php
index 71c1ce10798cd8fe6a835489847f5f52fb95585b..7774ccf87c914f8c036a0628dd1562c3f03ec2f2 100644
--- a/tests/modules/core/lib/Auth/Process/AttributeLimitTest.php
+++ b/tests/modules/core/lib/Auth/Process/AttributeLimitTest.php
@@ -20,7 +20,7 @@ class AttributeLimitTest extends TestCase
      * setUpBeforeClass a request that will be used for the following tests.
      * note the above tests don't use self::$request for processFilter input.
      */
-    protected static $request;
+    protected static array $request;
 
 
     /**
diff --git a/tests/modules/core/lib/Auth/Process/CardinalitySingleTest.php b/tests/modules/core/lib/Auth/Process/CardinalitySingleTest.php
index 76a7857bb3d2497ceccddc7d475f51616f4ac2fd..3f18d49d44ff6793e009c7bb7e657fab93b9675c 100644
--- a/tests/modules/core/lib/Auth/Process/CardinalitySingleTest.php
+++ b/tests/modules/core/lib/Auth/Process/CardinalitySingleTest.php
@@ -16,7 +16,7 @@ use SimpleSAML\Module\core\Auth\Process\CardinalitySingle;
 class CardinalitySingleTest extends TestCase
 {
     /** @var \SimpleSAML\Utils\HttpAdapter|\PHPUnit\Framework\MockObject\MockObject */
-    private $http;
+    private object $http;
 
 
     /**
diff --git a/tests/modules/core/lib/Auth/Process/CardinalityTest.php b/tests/modules/core/lib/Auth/Process/CardinalityTest.php
index 3441848815940d313321ceb46867437d1d6702ad..9934351ae9d4621768088ba732afa6423c376eba 100644
--- a/tests/modules/core/lib/Auth/Process/CardinalityTest.php
+++ b/tests/modules/core/lib/Auth/Process/CardinalityTest.php
@@ -18,7 +18,7 @@ use SimpleSAML\Utils\HttpAdapter;
 class CardinalityTest extends TestCase
 {
     /** @var \SimpleSAML\Utils\HttpAdapter|\PHPUnit\Framework\MockObject\MockObject */
-    private $http;
+    private object $http;
 
 
     /**
diff --git a/tests/modules/core/lib/Auth/Process/TargetedIDTest.php b/tests/modules/core/lib/Auth/Process/TargetedIDTest.php
index 2920d9386d2a744dcafab31d25e786d8b7796760..0bccc514e0afbed8a2340224f2af1bf822f3470f 100644
--- a/tests/modules/core/lib/Auth/Process/TargetedIDTest.php
+++ b/tests/modules/core/lib/Auth/Process/TargetedIDTest.php
@@ -20,10 +20,10 @@ use SimpleSAML\Utils;
 class TargetedIDTest extends TestCase
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Utils\Config */
-    protected static $configUtils;
+    protected static Utils\Config $configUtils;
 
     /**
      * Set up for each test.
diff --git a/tests/modules/core/lib/Controller/LoginTest.php b/tests/modules/core/lib/Controller/LoginTest.php
index bb539a01ad0bbebab83e3a2a4a34f2218a796c66..341885210608455c1c8b52a174bc74351e2cff7d 100644
--- a/tests/modules/core/lib/Controller/LoginTest.php
+++ b/tests/modules/core/lib/Controller/LoginTest.php
@@ -30,13 +30,13 @@ use Symfony\Component\HttpFoundation\Request;
 class LoginTest extends ClearStateTestCase
 {
     /** @var array */
-    protected $authSources;
+    protected array $authSources;
 
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Configuration[] */
-    protected $loadedConfigs;
+    protected array $loadedConfigs;
 
     /**
      * Set up for each test.
diff --git a/tests/modules/core/lib/Storage/SQLPermanentStorageTest.php b/tests/modules/core/lib/Storage/SQLPermanentStorageTest.php
index 204640081490b9fa7b9c634763c38a49119f9d2d..7e04f21ee2aa628d4fd49f829e4f8fcc47586749 100644
--- a/tests/modules/core/lib/Storage/SQLPermanentStorageTest.php
+++ b/tests/modules/core/lib/Storage/SQLPermanentStorageTest.php
@@ -16,7 +16,7 @@ use SimpleSAML\Module\core\Storage\SQLPermanentStorage;
 class SQLPermanentStorageTest extends TestCase
 {
     /** @var \SimpleSAML\Module\core\Storage\SQLPermanentStorage */
-    private static $sql;
+    private static SQLPermanentStorage $sql;
 
 
     /**
@@ -35,7 +35,6 @@ class SQLPermanentStorageTest extends TestCase
      */
     public static function tearDownAfterClass(): void
     {
-        self::$sql = null;
         unlink(sys_get_temp_dir() . '/sqllite/test.sqlite');
     }
 
diff --git a/tests/modules/cron/lib/Controller/CronTest.php b/tests/modules/cron/lib/Controller/CronTest.php
index d82da0d8af824838a1a40adcc28feb1fb3c99a23..da032e241f859bf93df551b754d637c7ebd97110 100644
--- a/tests/modules/cron/lib/Controller/CronTest.php
+++ b/tests/modules/cron/lib/Controller/CronTest.php
@@ -22,13 +22,13 @@ use Symfony\Component\HttpFoundation\Response;
 class CronTest extends TestCase
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
     /** @var \SimpleSAML\Utils\Auth */
-    protected $authUtils;
+    protected Utils\Auth $authUtils;
 
 
     /**
diff --git a/tests/modules/multiauth/lib/Auth/Source/MultiAuthTest.php b/tests/modules/multiauth/lib/Auth/Source/MultiAuthTest.php
index 68e72a13ebbfa9ebb0dcd1c0b0f6d02181754ccc..5760e213d72780b215e04740c215c54fe385b665 100644
--- a/tests/modules/multiauth/lib/Auth/Source/MultiAuthTest.php
+++ b/tests/modules/multiauth/lib/Auth/Source/MultiAuthTest.php
@@ -15,11 +15,11 @@ use SimpleSAML\Module\multiauth\Auth\Source\MultiAuth;
  */
 class MultiAuthTest extends ClearStateTestCase
 {
-    /** @var Configuration */
-    private $config;
+    /** @var \SimpleSAML\Configuration */
+    private Configuration $config;
 
-    /** @var Configuration */
-    private $sourceConfig;
+    /** @var \SimpleSAML\Configuration */
+    private Configuration $sourceConfig;
 
 
     /**
diff --git a/tests/modules/multiauth/lib/Controller/DiscoControllerTest.php b/tests/modules/multiauth/lib/Controller/DiscoControllerTest.php
index ffecbde7c869891bf20160f65727999f4c8f106d..a5ae6ff6b3ebe7bcf5c34b20eb57a6c8780c4574 100644
--- a/tests/modules/multiauth/lib/Controller/DiscoControllerTest.php
+++ b/tests/modules/multiauth/lib/Controller/DiscoControllerTest.php
@@ -25,10 +25,10 @@ use Symfony\Component\HttpFoundation\Response;
 class DiscoControllerTest extends TestCase
 {
     /** @var \SimpleSAML\Configuration */
-    protected $config;
+    protected Configuration $config;
 
     /** @var \SimpleSAML\Session */
-    protected $session;
+    protected Session $session;
 
 
     /**
diff --git a/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php b/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php
index 28c3bfca9a0d3f2f35ce3cbf77068da2f07906da..9c697ea1b753b6688440f522f2b7e73dc9717051 100644
--- a/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php
+++ b/tests/modules/saml/lib/Auth/Source/Auth_Source_SP_Test.php
@@ -25,13 +25,13 @@ use SimpleSAML\Test\Utils\SpTester;
 class SPTest extends ClearStateTestCase
 {
     /** @var \SimpleSAML\Configuration|null $idpMetadata */
-    private $idpMetadata = null;
+    private ?Configuration $idpMetadata = null;
 
     /** @var array $idpConfigArray */
-    private $idpConfigArray;
+    private array $idpConfigArray;
 
     /** @var \SimpleSAML\Configuration */
-    private $config;
+    private Configuration $config;
 
 
     /**
diff --git a/tests/modules/saml/lib/IdP/SAML2Test.php b/tests/modules/saml/lib/IdP/SAML2Test.php
index 503afddd1034c2c4e1dc5c7155446e45bf04f397..66f664332cc548207860688919e88fd8356edcf1 100644
--- a/tests/modules/saml/lib/IdP/SAML2Test.php
+++ b/tests/modules/saml/lib/IdP/SAML2Test.php
@@ -18,7 +18,7 @@ class SAML2Test extends ClearStateTestCase
      * Default values for the state array expected to be generated at the start of logins
      * @var array
      */
-    private $defaultExpectedAuthState = [
+    private array $defaultExpectedAuthState = [
         'Responder' => ['\SimpleSAML\Module\saml\IdP\SAML2', 'sendResponse'],
         '\SimpleSAML\Auth\State.exceptionFunc' => ['\SimpleSAML\Module\saml\IdP\SAML2', 'handleAuthError'],
         'saml:RelayState' => null,
diff --git a/tests/modules/saml/lib/IdP/SQLNameIDTest.php b/tests/modules/saml/lib/IdP/SQLNameIDTest.php
index f89e5bbc97161f41c264d20cc00a37c384a3c5d1..e33bd604e99d487a7202c8728a0aa8aa76b24ce7 100644
--- a/tests/modules/saml/lib/IdP/SQLNameIDTest.php
+++ b/tests/modules/saml/lib/IdP/SQLNameIDTest.php
@@ -106,7 +106,11 @@ class SQLNameIDTest extends TestCase
         $reflectedClass = new ReflectionClass($className);
         $reflectedInstance = $reflectedClass->getProperty('instance');
         $reflectedInstance->setAccessible(true);
-        $reflectedInstance->setValue($service, null);
+        if ($service instanceof Configuration) {
+            $reflectedInstance->setValue($service, []);
+        } else {
+            $reflectedInstance->setValue($service, null);
+        }
         $reflectedInstance->setAccessible(false);
     }
 }
diff --git a/tests/www/IndexTest.php b/tests/www/IndexTest.php
index 62183d57703a56bc40a986210c5c0590e3b41332..cd057203a0fa7d9146078ddd7eac2c0c20ec5641 100644
--- a/tests/www/IndexTest.php
+++ b/tests/www/IndexTest.php
@@ -19,22 +19,22 @@ class IndexTest extends TestCase
     /**
      * @var \SimpleSAML\TestUtils\BuiltInServer
      */
-    protected $server;
+    protected BuiltInServer $server;
 
     /**
      * @var string
      */
-    protected $server_addr;
+    protected string $server_addr;
 
     /**
      * @var int
      */
-    protected $server_pid;
+    protected int $server_pid;
 
     /**
      * @var string
      */
-    protected $shared_file;
+    protected string $shared_file;
 
 
     /**
diff --git a/www/saml2/idp/ArtifactResolutionService.php b/www/saml2/idp/ArtifactResolutionService.php
index bcec37713caced921d00994c9526c7178f8b3bb6..76cc4a18504ea194b628a0a1dbcc14a4a8870acc 100644
--- a/www/saml2/idp/ArtifactResolutionService.php
+++ b/www/saml2/idp/ArtifactResolutionService.php
@@ -15,6 +15,7 @@ use SAML2\ArtifactResponse;
 use SAML2\DOMDocumentFactory;
 use SAML2\SOAP;
 use SAML2\XML\saml\Issuer;
+use SimpleSAML\Assert\Assert;
 use SimpleSAML\Configuration;
 use SimpleSAML\Error;
 use SimpleSAML\Module;
@@ -57,7 +58,10 @@ if (!($request instanceof ArtifactResolve)) {
     throw new Exception('Message received on ArtifactResolutionService wasn\'t a ArtifactResolve request.');
 }
 
-$issuer = $request->getIssuer()->getValue();
+$issuer = $request->getIssuer();
+/** @psalm-assert \SAML2\XML\saml\Issuer $issuer */
+Assert::notNull($issuer);
+$issuer = $issuer->getValue();
 $spMetadata = $metadata->getMetaDataConfig($issuer, 'saml20-sp-remote');
 $artifact = $request->getArtifact();
 $responseData = $store->get('artifact', $artifact);
@@ -65,7 +69,7 @@ $store->delete('artifact', $artifact);
 
 if ($responseData !== null) {
     $document = DOMDocumentFactory::fromString($responseData);
-    $responseXML = $document->firstChild;
+    $responseXML = $document->documentElement;
 } else {
     $responseXML = null;
 }
diff --git a/www/saml2/idp/initSLO.php b/www/saml2/idp/initSLO.php
index e6c7f26f61ccec1885a88cba4c8fb611ea3149da..f86b49488ba98645997f81ba1ef8a46484aa4eb8 100644
--- a/www/saml2/idp/initSLO.php
+++ b/www/saml2/idp/initSLO.php
@@ -5,7 +5,7 @@ require_once('../../_include.php');
 use SimpleSAML\Assert\Assert;
 use SimpleSAML\Configuration;
 use SimpleSAML\Error;
-use SimpleSAML\Idp;
+use SimpleSAML\IdP;
 use SimpleSAML\Logger;
 use SimpleSAML\Metadata;
 use SimpleSAML\Module;
diff --git a/www/saml2/idp/metadata.php b/www/saml2/idp/metadata.php
index f9534c48cd19db8763255183a89b3b92bf18556f..7bf640076a46786ea18b9e4135af9756ae115881 100644
--- a/www/saml2/idp/metadata.php
+++ b/www/saml2/idp/metadata.php
@@ -201,9 +201,11 @@ try {
 
     $technicalContactEmail = $config->getString('technicalcontact_email', false);
     if ($technicalContactEmail && $technicalContactEmail !== 'na@example.org') {
-        $techcontact['emailAddress'] = $technicalContactEmail;
-        $techcontact['name'] = $config->getString('technicalcontact_name', null);
-        $techcontact['contactType'] = 'technical';
+        $techcontact = [
+            'emailAddress' => $technicalContactEmail,
+            'name' => $config->getString('technicalcontact_name', null),
+            'contactType' => 'technical',
+        ];
         $metaArray['contacts'][] = Metadata::getContact($techcontact);
     }