diff --git a/composer.json b/composer.json
index 351fbbd276c4633cb5aed62be7ffdcfe4defa0b0..c2d4482b5409fa8275a6c9ab435c8635d7dc545c 100644
--- a/composer.json
+++ b/composer.json
@@ -59,8 +59,8 @@
         "gettext/gettext": "^5.6.1",
         "gettext/translator": "^1.0.1",
         "phpmailer/phpmailer": "^6.5",
-        "simplesamlphp/assert": "^0.2.11",
-        "simplesamlphp/saml2": "^4.5",
+        "simplesamlphp/assert": "^0.3.0",
+        "simplesamlphp/saml2": "^4.6",
         "symfony/cache": "^5.4",
         "symfony/config": "^5.4",
         "symfony/console": "^5.4",
@@ -83,9 +83,9 @@
         "ext-curl": "*",
         "ext-pdo_sqlite": "*",
         "mikey179/vfsstream": "~1.6",
-        "simplesamlphp/simplesamlphp-module-adfs": ">=2.0.0-rc1",
-        "simplesamlphp/simplesamlphp-test-framework": "^1.2.0",
-        "simplesamlphp/xml-security": "^0.4.1"
+        "simplesamlphp/simplesamlphp-module-adfs": ">=2.0.0-rc2",
+        "simplesamlphp/simplesamlphp-test-framework": "^1.2.1",
+        "simplesamlphp/xml-security": "^0.4.5"
     },
     "suggest": {
         "predis/predis": "Needed if a Redis server is used to store session information",
diff --git a/composer.lock b/composer.lock
index bf545f4734e526047652774b3090fd37ef84b25e..9868e21548baf4ffd0c523d07710d0d4b25fd562 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "628d965ff7eff1289f11a49069eb444a",
+    "content-hash": "781df46fee6b65e44c773fdfae506d2c",
     "packages": [
         {
             "name": "composer/ca-bundle",
@@ -84,16 +84,16 @@
         },
         {
             "name": "composer/composer",
-            "version": "2.3.6",
+            "version": "2.3.7",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/composer.git",
-                "reference": "0f43aa1652c447a6bc7c9217ec133313b1d32e72"
+                "reference": "10cd375cf85dede2ff417ceab517ef9a0dc55407"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/composer/zipball/0f43aa1652c447a6bc7c9217ec133313b1d32e72",
-                "reference": "0f43aa1652c447a6bc7c9217ec133313b1d32e72",
+                "url": "https://api.github.com/repos/composer/composer/zipball/10cd375cf85dede2ff417ceab517ef9a0dc55407",
+                "reference": "10cd375cf85dede2ff417ceab517ef9a0dc55407",
                 "shasum": ""
             },
             "require": {
@@ -136,6 +136,11 @@
             "extra": {
                 "branch-alias": {
                     "dev-main": "2.3-dev"
+                },
+                "phpstan": {
+                    "includes": [
+                        "phpstan/rules.neon"
+                    ]
                 }
             },
             "autoload": {
@@ -169,7 +174,7 @@
             "support": {
                 "irc": "ircs://irc.libera.chat:6697/composer",
                 "issues": "https://github.com/composer/composer/issues",
-                "source": "https://github.com/composer/composer/tree/2.3.6"
+                "source": "https://github.com/composer/composer/tree/2.3.7"
             },
             "funding": [
                 {
@@ -185,7 +190,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-06-01T19:57:13+00:00"
+            "time": "2022-06-06T14:43:28+00:00"
         },
         {
             "name": "composer/metadata-minifier",
@@ -1353,16 +1358,16 @@
         },
         {
             "name": "simplesamlphp/assert",
-            "version": "v0.2.13",
+            "version": "v0.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/simplesamlphp/assert.git",
-                "reference": "72a16329cf95b148717aadd258fbe36ac96cf004"
+                "reference": "d9856ac52592ade2303b7101f7434544b4a03c86"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/simplesamlphp/assert/zipball/72a16329cf95b148717aadd258fbe36ac96cf004",
-                "reference": "72a16329cf95b148717aadd258fbe36ac96cf004",
+                "url": "https://api.github.com/repos/simplesamlphp/assert/zipball/d9856ac52592ade2303b7101f7434544b4a03c86",
+                "reference": "d9856ac52592ade2303b7101f7434544b4a03c86",
                 "shasum": ""
             },
             "require": {
@@ -1371,12 +1376,12 @@
                 "webmozart/assert": "^1.10"
             },
             "require-dev": {
-                "simplesamlphp/simplesamlphp-test-framework": "^1.0.5"
+                "simplesamlphp/simplesamlphp-test-framework": "^1.2.1"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "v0.1.x-dev"
+                    "dev-master": "v0.2.x-dev"
                 }
             },
             "autoload": {
@@ -1401,22 +1406,22 @@
             "description": "A wrapper around webmozart/assert to make it useful beyond checking method arguments",
             "support": {
                 "issues": "https://github.com/simplesamlphp/assert/issues",
-                "source": "https://github.com/simplesamlphp/assert/tree/v0.2.13"
+                "source": "https://github.com/simplesamlphp/assert/tree/v0.3.0"
             },
-            "time": "2022-02-17T21:38:59+00:00"
+            "time": "2022-06-12T19:19:19+00:00"
         },
         {
             "name": "simplesamlphp/saml2",
-            "version": "v4.6.1",
+            "version": "v4.6.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/simplesamlphp/saml2.git",
-                "reference": "5e46819fdb76657f13e05a8f264d06efd9163c3d"
+                "reference": "bfc9c79dd6b728a41d1de988f545f6e64728a51d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/5e46819fdb76657f13e05a8f264d06efd9163c3d",
-                "reference": "5e46819fdb76657f13e05a8f264d06efd9163c3d",
+                "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/bfc9c79dd6b728a41d1de988f545f6e64728a51d",
+                "reference": "bfc9c79dd6b728a41d1de988f545f6e64728a51d",
                 "shasum": ""
             },
             "require": {
@@ -1424,7 +1429,7 @@
                 "ext-openssl": "*",
                 "ext-zlib": "*",
                 "php": ">=7.1 || ^8.0",
-                "psr/log": "~1.1",
+                "psr/log": "~1.1 || ^2.0 || ^3.0",
                 "robrichards/xmlseclibs": "^3.1.1",
                 "webmozart/assert": "^1.9"
             },
@@ -1459,9 +1464,9 @@
             "description": "SAML2 PHP library from SimpleSAMLphp",
             "support": {
                 "issues": "https://github.com/simplesamlphp/saml2/issues",
-                "source": "https://github.com/simplesamlphp/saml2/tree/v4.6.1"
+                "source": "https://github.com/simplesamlphp/saml2/tree/v4.6.3"
             },
-            "time": "2022-05-23T20:49:55+00:00"
+            "time": "2022-06-13T14:04:10+00:00"
         },
         {
             "name": "symfony/cache",
@@ -6772,32 +6777,32 @@
         },
         {
             "name": "simplesamlphp/simplesamlphp-module-adfs",
-            "version": "v2.0.0-rc9",
+            "version": "v2.0.0-rc2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/simplesamlphp/simplesamlphp-module-adfs.git",
-                "reference": "864c03ae1627854f274b02ff91cfb35e2db08c1b"
+                "reference": "036208c8bbf795bca9ab8845f7288923a4dab3da"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-module-adfs/zipball/864c03ae1627854f274b02ff91cfb35e2db08c1b",
-                "reference": "864c03ae1627854f274b02ff91cfb35e2db08c1b",
+                "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-module-adfs/zipball/036208c8bbf795bca9ab8845f7288923a4dab3da",
+                "reference": "036208c8bbf795bca9ab8845f7288923a4dab3da",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.4 || ^8.0",
-                "simplesamlphp/assert": "^0.2.11",
+                "simplesamlphp/assert": "^0.3.0",
                 "simplesamlphp/composer-module-installer": "^1.1.7",
                 "simplesamlphp/xml-security": "~0.4.1"
             },
             "require-dev": {
-                "simplesamlphp/simplesamlphp": "^2.0.0-beta.9",
-                "simplesamlphp/simplesamlphp-test-framework": "^1.1.6"
+                "simplesamlphp/simplesamlphp": "^2.0.0-beta.10",
+                "simplesamlphp/simplesamlphp-test-framework": "^1.2.1"
             },
             "type": "simplesamlphp-module",
             "autoload": {
                 "psr-4": {
-                    "SimpleSAML\\Module\\adfs\\": "lib/"
+                    "SimpleSAML\\Module\\adfs\\": "src/"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -6819,7 +6824,7 @@
                 "issues": "https://github.com/simplesamlphp/simplesamlphp-module-adfs/issues",
                 "source": "https://github.com/simplesamlphp/simplesamlphp-module-adfs"
             },
-            "time": "2022-04-08T10:07:24+00:00"
+            "time": "2022-06-12T19:37:10+00:00"
         },
         {
             "name": "simplesamlphp/simplesamlphp-test-framework",
@@ -6880,26 +6885,27 @@
         },
         {
             "name": "simplesamlphp/xml-common",
-            "version": "v0.8.8",
+            "version": "v0.8.9",
             "source": {
                 "type": "git",
                 "url": "https://github.com/simplesamlphp/xml-common.git",
-                "reference": "b8774b31f9f5a2c4e3c7c37d5eafe3cc4aed2687"
+                "reference": "f53d56920bf91b18fc5471ab9ed00cae1d186fc0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/simplesamlphp/xml-common/zipball/b8774b31f9f5a2c4e3c7c37d5eafe3cc4aed2687",
-                "reference": "b8774b31f9f5a2c4e3c7c37d5eafe3cc4aed2687",
+                "url": "https://api.github.com/repos/simplesamlphp/xml-common/zipball/f53d56920bf91b18fc5471ab9ed00cae1d186fc0",
+                "reference": "f53d56920bf91b18fc5471ab9ed00cae1d186fc0",
                 "shasum": ""
             },
             "require": {
                 "ext-dom": "*",
                 "ext-spl": "*",
                 "php": ">=7.4 || ^8.0",
-                "simplesamlphp/assert": "~0.2.11"
+                "simplesamlphp/assert": "^0.3.0"
             },
             "require-dev": {
-                "simplesamlphp/simplesamlphp-test-framework": "^1.1.5"
+                "simplesamlphp/simplesamlphp-test-framework": "^1.2.1",
+                "vimeo/psalm": "^5.0.0-beta1"
             },
             "type": "project",
             "autoload": {
@@ -6934,20 +6940,20 @@
                 "issues": "https://github.com/simplesamlphp/xml-common/issues",
                 "source": "https://github.com/simplesamlphp/xml-common"
             },
-            "time": "2022-04-08T13:37:27+00:00"
+            "time": "2022-06-12T19:40:54+00:00"
         },
         {
             "name": "simplesamlphp/xml-security",
-            "version": "v0.4.4",
+            "version": "v0.4.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/simplesamlphp/xml-security.git",
-                "reference": "fb15329181a36838b164d9c13e4df4061d4de636"
+                "reference": "058ec7fc5302815cadcaaaf0034298e76b1c7be3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/simplesamlphp/xml-security/zipball/fb15329181a36838b164d9c13e4df4061d4de636",
-                "reference": "fb15329181a36838b164d9c13e4df4061d4de636",
+                "url": "https://api.github.com/repos/simplesamlphp/xml-security/zipball/058ec7fc5302815cadcaaaf0034298e76b1c7be3",
+                "reference": "058ec7fc5302815cadcaaaf0034298e76b1c7be3",
                 "shasum": ""
             },
             "require": {
@@ -6956,11 +6962,11 @@
                 "ext-spl": "*",
                 "php": ">= 7.4 || ^8.0",
                 "robrichards/xmlseclibs": "^3.1.1",
-                "simplesamlphp/assert": "~0.2.13",
+                "simplesamlphp/assert": "^0.3.0",
                 "simplesamlphp/xml-common": "^0.8.8"
             },
             "require-dev": {
-                "simplesamlphp/simplesamlphp-test-framework": "^1.1.7"
+                "simplesamlphp/simplesamlphp-test-framework": "^1.2.1"
             },
             "type": "library",
             "autoload": {
@@ -6994,9 +7000,9 @@
             ],
             "support": {
                 "issues": "https://github.com/simplesamlphp/xml-security/issues",
-                "source": "https://github.com/simplesamlphp/xml-security/tree/v0.4.4"
+                "source": "https://github.com/simplesamlphp/xml-security/tree/v0.4.5"
             },
-            "time": "2022-05-02T22:30:04+00:00"
+            "time": "2022-06-12T19:39:40+00:00"
         },
         {
             "name": "squizlabs/php_codesniffer",
diff --git a/docs/simplesamlphp-artifact-idp.md b/docs/simplesamlphp-artifact-idp.md
index 75286aeaf58da4f7316b5f3d499453650a7d98f2..6d993fa9e6f374eac9b8599f09d1dca4a236ea0a 100644
--- a/docs/simplesamlphp-artifact-idp.md
+++ b/docs/simplesamlphp-artifact-idp.md
@@ -35,7 +35,7 @@ Enabling artifact on the IdP
 
 To enable the IdP to send artifacts, you must add the `saml20.sendartifact` option to the `saml20-idp-hosted` metadata file:
 
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         [....]
         'auth' => 'example-userpass',
         'saml20.sendartifact' => TRUE,
@@ -89,7 +89,7 @@ You may therefore have to add the webserver certificate to the metadata that you
 To do this, you need to set the `https.certificate` option in the `saml20-idp-hosted` metadata file.
 That option should refer to a file containing the webserver certificate.
 
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         [....]
         'auth' => 'example-userpass',
         'saml20.sendartifact' => TRUE,
diff --git a/docs/simplesamlphp-authproc.md b/docs/simplesamlphp-authproc.md
index 478070c5cc575bcf217883f44c60cd3c2673eb79..a8ab604b702e70fc4064d528c7ef51eff36bbfc8 100644
--- a/docs/simplesamlphp-authproc.md
+++ b/docs/simplesamlphp-authproc.md
@@ -98,15 +98,17 @@ The filters in `authproc.sp` will be executed at the SP side regardless of which
 
 Filters can be added both in `hosted` and `remote` metadata. Here is an example of a filter added in a metadata file:
 
-	'__DYNAMIC:1__' => [
-		'host'				=>	'__DEFAULT_',
-		'privatekey'		=>	'example.org.pem',
-		'certificate'		=>	'example.org.crt',
-		'auth'				=>	'feide',
-		'authproc' => [
-			40 => 'core:TargetedID',
-		],
-	]
+```php
+'urn:x-simplesamlphp:example-idp' => [
+    'host' => '__DEFAULT_',
+    'privatekey' => 'example.org.pem',
+    'certificate' => 'example.org.crt',
+    'auth' => 'feide',
+    'authproc' => [
+        40 => 'core:TargetedID',
+    ],
+]
+```
 
 The example above is in `saml20-idp-hosted`.
 
diff --git a/docs/simplesamlphp-customauth.md b/docs/simplesamlphp-customauth.md
index 83013f0860e4b9f074c0be7bb3de62dd9c790467..cb3fe97739167c30ea7f2e80e45c9af937792acf 100644
--- a/docs/simplesamlphp-customauth.md
+++ b/docs/simplesamlphp-customauth.md
@@ -120,7 +120,7 @@ In that file you should locate the `auth`-option for your IdP, and change it to
 
     <?php
     /* ... */
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         /* ... */
         /*
          * Authentication source to use. Must be one that is configured in
diff --git a/docs/simplesamlphp-ecp-idp.md b/docs/simplesamlphp-ecp-idp.md
index 566df182d610f989b349ee5a74aa4631d5ff3f3d..c61818dcc437672139091ec900ba4bf3b4736bbc 100644
--- a/docs/simplesamlphp-ecp-idp.md
+++ b/docs/simplesamlphp-ecp-idp.md
@@ -19,7 +19,7 @@ Enabling ECP Profile on the IdP
 
 To enable the IdP to send ECP assertions you must add the `saml20.ecp` option to the `saml20-idp-hosted` metadata file:
 
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         [....]
         'auth' => 'example-userpass',
         'saml20.ecp' => true,
diff --git a/docs/simplesamlphp-googleapps.md b/docs/simplesamlphp-googleapps.md
index b83a3b01773b1298692a028d6d698efad2f2589d..3058d97b38926a6ec4e98d154d1e6ff237fd7714 100644
--- a/docs/simplesamlphp-googleapps.md
+++ b/docs/simplesamlphp-googleapps.md
@@ -130,18 +130,20 @@ If you want to setup a SAML 2.0 IdP for Google Workspace, you need to configure
 
 This is the configuration of the IdP itself. Here is some example config:
 
-	// The SAML entity ID is the index of this config. Dynamic:X will automatically generate an entity ID (recommended)
-	$metadata['__DYNAMIC:1__'] => [
-		
-		// The hostname of the server (VHOST) that this SAML entity will use.
-		'host'				=>	'__DEFAULT__',
-		
-		// X.509 key and certificate. Relative to the cert directory.
-		'privatekey'   => 'googleworkspaceidp.pem',
-		'certificate'  => 'googleappsidp.crt',
-		
-		'auth' => 'example-userpass',
-	]
+```php
+// The SAML entity ID is the index of this config.
+$metadata['urn:x-simplesamlphp:example-idp'] => [
+
+    // The hostname of the server (VHOST) that this SAML entity will use.
+    'host' => '__DEFAULT__',
+
+    // X.509 key and certificate. Relative to the cert directory.
+    'privatekey'   => 'googleworkspaceidp.pem',
+    'certificate'  => 'googleappsidp.crt',
+
+    'auth' => 'example-userpass',
+]
+```
 
 **Note**: You can only have one entry in the file with host equal to `__DEFAULT__`, therefore you should replace the existing entry with this one, instead of adding this entry as a new entry in the file. 
 
diff --git a/docs/simplesamlphp-hok-idp.md b/docs/simplesamlphp-hok-idp.md
index 7bf375e1b332baaaa0f53f2309b53a813defbda6..872fc05bfa7b1effb697a926a3226d953279a9f6 100644
--- a/docs/simplesamlphp-hok-idp.md
+++ b/docs/simplesamlphp-hok-idp.md
@@ -29,7 +29,7 @@ Enabling HoK SSO Profile on the IdP
 
 To enable the IdP to send HoK assertions you must add the `saml20.hok.assertion` option to the `saml20-idp-hosted` metadata file:
 
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         [....]
         'auth' => 'example-userpass',
         'saml20.hok.assertion' => TRUE,
diff --git a/docs/simplesamlphp-idp.md b/docs/simplesamlphp-idp.md
index 20847f247f08e4db89181279a4087bc39779ff24..2ba329a11222b7cadfcbd13fcc2e508dc59d6427 100644
--- a/docs/simplesamlphp-idp.md
+++ b/docs/simplesamlphp-idp.md
@@ -142,7 +142,7 @@ The SAML 2.0 IdP is configured by the metadata stored in
 This is a minimal configuration:
 
     <?php
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         /*
          * The hostname for this IdP. This makes it possible to run multiple
          * IdPs from the same configuration. '__DEFAULT__' means that this one
diff --git a/docs/simplesamlphp-metadata-extensions-rpi.md b/docs/simplesamlphp-metadata-extensions-rpi.md
index f824f6ae275f3260c33ea4e45c9203688b5b6631..9371cd89c2e71e0352ca8852b128aa58d888ed1e 100644
--- a/docs/simplesamlphp-metadata-extensions-rpi.md
+++ b/docs/simplesamlphp-metadata-extensions-rpi.md
@@ -72,7 +72,7 @@ Service Provider:
 
 Identity Provider:
 
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         'host' => '__DEFAULT__',
         ...
         'RegistrationInfo' => [
diff --git a/docs/simplesamlphp-modules.md b/docs/simplesamlphp-modules.md
index c53527ff4d3eb68161b47b6bd7fcb5dfcddfa809..15fcdf08dd12ba7280c7c126a5818b99f3f3d185 100644
--- a/docs/simplesamlphp-modules.md
+++ b/docs/simplesamlphp-modules.md
@@ -154,7 +154,7 @@ this:
 To use this authentication source in a SAML 2.0 IdP, set the
 `auth`-option of the IdP to `'example-static'`:
 
-    '__DYNAMIC:1__' => [
+    'urn:x-simplesamlphp:example-idp' => [
       'host' => '__DEFAULT__',
       'privatekey' => 'example.org.pem',
       'certificate' => 'example.org.crt',
diff --git a/docs/simplesamlphp-reference-idp-hosted.md b/docs/simplesamlphp-reference-idp-hosted.md
index ea64aa3b30424d87a294546bd1efb9e4cb907e83..7b7740961a1830d7834dcbb86c4ae577b444f860 100644
--- a/docs/simplesamlphp-reference-idp-hosted.md
+++ b/docs/simplesamlphp-reference-idp-hosted.md
@@ -18,9 +18,7 @@ Both files have the following format:
     ];
     /* ... */
 
-The entity ID should be an URI. It can, also be on the form
-`__DYNAMIC:1__`, `__DYNAMIC:2__`, `...`. In that case, the entity ID
-will be generated automatically.
+The entity ID must be a URI.
 
 The `host` option is the hostname of the IdP, and will be used to
 select the correct configuration. One entry in the metadata-list can
@@ -392,11 +390,8 @@ These are some examples of IdP metadata
 ### Minimal SAML 2.0 IdP ###
 
     <?php
-    /*
-     * We use the '__DYNAMIC:1__' entity ID so that the entity ID
-     * will be autogenerated.
-     */
-    $metadata['__DYNAMIC:1__'] = [
+
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         /*
          * We use '__DEFAULT__' as the hostname so we won't have to
          * enter a hostname.
@@ -425,7 +420,7 @@ $republishTarget = $dom->createElementNS('http://eduid.cz/schema/metadata/1.0',
 $republishRequest->appendChild($republishTarget);
 $ext = [new \SAML2\XML\Chunk($republishRequest)];
 
-$metadata['__DYNAMIC:1__'] = [
+$metadata['urn:x-simplesamlphp:example-idp'] = [
     'host' => '__DEFAULT__',
     'certificate' => 'example.org.crt',
     'privatekey' => 'example.org.pem',
diff --git a/docs/simplesamlphp-sp.md b/docs/simplesamlphp-sp.md
index b74d706d1c26dde52bc1c90a1ec90ae1cb878b85..6aade7b6350ee66c99b1c7f39166af6e3d41a521 100644
--- a/docs/simplesamlphp-sp.md
+++ b/docs/simplesamlphp-sp.md
@@ -1,11 +1,12 @@
-SimpleSAMLphp Service Provider QuickStart
-=========================================
+# SimpleSAMLphp Service Provider QuickStart
 
 [TOC]
 
-This guide will describe how to configure SimpleSAMLphp as a service provider (SP). You should previously have installed SimpleSAMLphp as described in [the SimpleSAMLphp installation instructions](simplesamlphp-install).
-
+This guide will describe how to configure SimpleSAMLphp as a service
+provider (SP). You should previously have installed SimpleSAMLphp as
+described in the [SimpleSAMLphp installation instructions](installation).
 
+[installation]: simplesamlphp-install
 
 Configuring the SP
 ------------------
@@ -21,13 +22,17 @@ $config = [
     /* This is the name of this authentication source, and will be used to access it later. */
     'default-sp' => [
         'saml:SP',
+        'entityID' => 'https://sp1.example.org/',
     ],
 ];
 ```
 
-For more information about additional options available for the SP, see the [`saml:SP` reference](./saml:sp).
+For more information about additional options available for the SP,
+see the [`saml:SP` reference](./saml:sp).
 
-If you want multiple Service Providers in the same site and installation, you can add more entries in the `authsources.php` configuration. If so remember to set the EntityID explicitly. Here is an example:
+If you want multiple Service Providers in the same site and installation,
+you can add more entries in the `authsources.php` configuration. If so
+remember to set the EntityID explicitly. Here is an example:
 
 ```php
     'sp1' => [
@@ -42,13 +47,17 @@ If you want multiple Service Providers in the same site and installation, you ca
 
 ### Enabling a certificate for your Service Provider
 
-Some Identity Providers / Federations may require that your Service Providers holds a certificate. If you enable a certificate for your Service Provider, it may be able to sign requests and response sent to the Identity Provider, as well as receiving encrypted responses.
+Some Identity Providers / Federations may require that your Service Providers
+holds a certificate. If you enable a certificate for your Service Provider,
+it may be able to sign requests and response sent to the Identity Provider,
+as well as receiving encrypted responses.
 
 Create a self-signed certificate in the `cert/` directory.
 
-	cd cert
-	openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out saml.crt -keyout saml.pem
-
+```bash
+cd cert
+openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out saml.crt -keyout saml.pem
+```
 
 Then edit your `authsources.php` entry, and add references to your certificate:
 
@@ -63,8 +72,12 @@ Then edit your `authsources.php` entry, and add references to your certificate:
 Adding IdPs to the SP
 ---------------------
 
-The service provider you are configuring needs to know about the identity providers you are going to connect to it. This is configured by metadata stored in `metadata/saml20-idp-remote.php`.
-This is a minimal example of a `metadata/saml20-idp-remote.php` metadata file:
+The service provider you are configuring needs to know about the identity
+providers you are going to connect to it. This is configured by metadata
+stored in `metadata/saml20-idp-remote.php`.
+
+This is a minimal example of a `metadata/saml20-idp-remote.php`
+metadata file:
 
 ```php
 <?php
@@ -75,20 +88,26 @@ $metadata['https://example.com'] = [
 ];
 ```
 
-`example.pem` under your `cert/` directory contains the certificate the identity provider uses for signing assertions.
+`example.pem` under your `cert/` directory contains the certificate the
+identity provider uses for signing assertions.
 
-For more information about available options in the idp-remote metadata files, see the [IdP remote reference](simplesamlphp-reference-idp-remote).
+For more information about available options in the idp-remote metadata
+files, see the [IdP remote reference](simplesamlphp-reference-idp-remote).
 
-If you have the metadata of the remote IdP as an XML file, you can use the built-in XML to SimpleSAMLphp metadata converter, which by default is available as `/admin/metadata-converter.php` in your SimpleSAMLphp installation.
+If you have the metadata of the remote IdP as an XML file, you can use the
+built-in XML to SimpleSAMLphp metadata converter, which by default is
+available at `/module.php/admin/federation/metadata-converter` in
+your SimpleSAMLphp installation.
 
-Note that the idp-remote file lists all IdPs you trust. You should remove all IdPs that you don't use.
+Note that the idp-remote file lists all IdPs you trust.
+You should remove all IdPs that you don't use.
 
 
 Setting the default IdP
 -----------------------
 
-An option in the authentication source allows you to configure which IdP should be used.
-This is the `idp` option.
+An option in the authentication source allows you to configure which IdP should
+be used. This is the `idp` option.
 
 ```php
 <?php
@@ -109,36 +128,46 @@ $config = [
 Exchange metadata with the IdP
 ------------------------------
 
-In order to complete the connection between your SP and an IdP, you must exchange the metadata of your SP with the IdP.
-The metadata of your SP can be found in the *Federation* tab of the web interface. Copy the SAML 2.0 XML Metadata document
-automatically generated by SimpleSAMLphp and send it to the administrator of the IdP. You can also send them the dedicated
-URL of your metadata, so that they can fetch it periodically and obtain automatically any changes that you may perform to
-your SP.
-
-You will also need to add the metadata of the IdP. Ask them to provide you with their metadata, and parse it using the *XML to
-SimpleSAMLphp metadata converter* tool available also in the *Federation* tab of the web interface. Copy the resulting
-parsed metadata and paste it with a text editor into the `metadata/saml20-idp-remote.php` file in your SimpleSAMLphp
-directory.
-
-If you intend to add your SP to a federation, the procedure for managing trust in federations will differ, but the common part is that you would need to provide the *SAML 2.0 metadata of your SP*, and register that with the federation administration.
-You will probably be required too to consume the federation metadata periodically. Read more about
-[automated metadata management](./metarefresh:simplesamlphp-automated_metadata) to learn more about that. 
+In order to complete the connection between your SP and an IdP, you must
+exchange the metadata of your SP with the IdP. The metadata of your SP can be
+found in the *Federation* tab of the web interface. Copy the SAML 2.0 XML
+Metadata document automatically generated by SimpleSAMLphp and send it to the
+administrator of the IdP. You can also send them the dedicated URL of your
+metadata, so that they can fetch it periodically and obtain automatically any
+changes that you may perform to your SP.
+
+You will also need to add the metadata of the IdP. Ask them to provide you with
+their metadata, and parse it using the *XML to SimpleSAMLphp metadata converter*
+tool available also in the *Federation* tab of the web interface. Copy the
+resulting parsed metadata and paste it with a text editor into the
+`metadata/saml20-idp-remote.php` file in your SimpleSAMLphp directory.
+
+If you intend to add your SP to a federation, the procedure for managing trust
+in federations will differ, but the common part is that you would need to
+provide the *SAML 2.0 metadata of your SP*, and register that with the
+federation administration. You will probably be required too to consume
+the federation metadata periodically. Read more about
+[automated metadata management](./metarefresh:simplesamlphp-automated_metadata)
+to learn more about that. 
 
 
 Test the SP
------------------------------
+-----------
 
-After the metadata is configured on the IdP, you should be able to test the configuration.
-The admin module of SimpleSAMLphp has a tab to test authentication sources.
-There you should a list of authentication sources, including the one you have created for the SP.
+After the metadata is configured on the IdP, you should be able to test the
+configuration. The admin module of SimpleSAMLphp has a tab to test
+authentication sources. There you should a list of authentication sources,
+including the one you have created for the SP.
 
-After you click the link for that authentication source, you will be redirected to the IdP.
-After entering your credentials, you should be redirected back to the test page.
+After you click the link for that authentication source, you will be
+redirected to the IdP. After entering your credentials, you should be
+redirected back to the test page.
 The test page should contain a list of your attributes:
 
 ![Screenshot of the status page after a user has succesfully authenticated](resources/simplesamlphp-sp/screenshot-example.png)
 
-For a better looking, more advanced Discovery Service with tabs and live search, you may want to use the `discopower` module.
+For a better looking, more advanced Discovery Service with tabs and live
+search, you may want to use the `discopower` module.
 
 Integrating authentication with your own application
 ----------------------------------------------------
@@ -154,7 +183,8 @@ lines of PHP code:
 
 Example code:
 
-We start off with loading a file which registers the SimpleSAMLphp classes with the autoloader.
+We start off with loading a file which registers the SimpleSAMLphp classes
+with the autoloader.
 
 ```php
 require_once('../../src/_autoload.php');
@@ -179,7 +209,9 @@ $attributes = $as->getAttributes();
 print_r($attributes);
 ```
 
-Each attribute name can be used as an index into $attributes to obtain the value. Every attribute value is an array - a single-valued attribute is an array of a single element.
+Each attribute name can be used as an index into $attributes to obtain the
+value. Every attribute value is an array - a single-valued attribute is an
+array of a single element.
 
 We can also request authentication with a specific IdP:
 
@@ -190,21 +222,28 @@ $as->login([
 ```
 
 Other options are also available.
-Take a look in the documentation for the [SP module](./saml:sp) for a list of all parameters.
+Take a look in the documentation for the [SP module](./saml:sp) for a list
+of all parameters.
 
-If we are using PHP sessions in SimpleSAMLphp and in the application we are protecting, SimpleSAMLphp will close any
-existing session when invoked for the first time, and its own session will prevail afterwards. If you want to restore
-your own session after calling SimpleSAMLphp, you can do so by cleaning up the session like this:
+If we are using PHP sessions in SimpleSAMLphp and in the application we are
+protecting, SimpleSAMLphp will close any existing session when invoked for the
+first time, and its own session will prevail afterwards. If you want to restore
+your own session after calling SimpleSAMLphp, you can do so by cleaning up the
+session like this:
 
 ```php
 $session = \SimpleSAML\Session::getSessionFromRequest();
 $session->cleanup();
 ```
 
-If you don't cleanup SimpleSAMLphp's session and try to use $_SESSION afterwards, you won't be using your own session
-and all your data is likely to get lost or inaccessible.
+If you don't cleanup SimpleSAMLphp's session and try to use $_SESSION
+afterwards, you won't be using your own session and all your data is
+likely to get lost or inaccessible.
 
-Note that if your application uses a [custom session handler](https://www.php.net/manual/en/function.session-set-save-handler.php), SimpleSAMLphp will use it as well. This can lead to problems because SimpleSAMLphp's stand-alone web UI uses the default PHP session handlers. Therefore, you may need to unset the custom handler before making any calls to SimpleSAMLphp:
+Note that if your application uses a [custom session handler](https://www.php.net/manual/en/function.session-set-save-handler.php),
+SimpleSAMLphp will use it as well. This can lead to problems because
+SimpleSAMLphp's stand-alone web UI uses the default PHP session handlers.
+Therefore, you may need to unset the custom handler before making any calls to SimpleSAMLphp:
 
 ```php
 // use custom save handler
@@ -229,7 +268,11 @@ session_start();
 Support
 -------
 
-If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
+If you need help to make this work, or want to discuss SimpleSAMLphp with other
+users of the software, you are fortunate: Around SimpleSAMLphp there is a great
+Open source community, and you are welcome to join! The forums are open for you
+to ask questions, contribute answers other further questions, request
+improvements or contribute with code or plugins of your own.
 
 -  [SimpleSAMLphp homepage](https://simplesamlphp.org)
 -  [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
diff --git a/docs/simplesamlphp-upgrade-notes-2.0.md b/docs/simplesamlphp-upgrade-notes-2.0.md
index 0950aafc4fee5e96fdc36925f199e67e8d7288e1..a2db80475c39d10bf9b6751f033eac79fb3e2eb0 100644
--- a/docs/simplesamlphp-upgrade-notes-2.0.md
+++ b/docs/simplesamlphp-upgrade-notes-2.0.md
@@ -32,6 +32,10 @@ Functional changes
 - All support for the Shibboleth 1.3 / SAML 1.1 protocol has been removed.
 - Sessions are no longer backwards compatible with previous versions. Make sure to clear your session cache during
   the upgrade process. How to do this depends on your session backend.
+- EntityIDs are no longer auto-generated. Make sure to set it to something sensible in the array-keys in
+  `metadata/saml20-idp-hosted.php` (or to the existing entityID when upgrading an existing installation).
+  If you are using a database to store metadata, make sure to replace any __DYNAMIC% entityID's with
+  a real value manually. Dynamic records are no longer loaded from the database.
 
 Configuration changes
 ---------------------
diff --git a/metadata-templates/saml20-idp-hosted.php b/metadata-templates/saml20-idp-hosted.php
index 79dc926d6a8fc2fcdabf826ddbcdb935c47b23d0..bcc7aeaf6912967c06fe4374defe1f18dcea9ab7 100644
--- a/metadata-templates/saml20-idp-hosted.php
+++ b/metadata-templates/saml20-idp-hosted.php
@@ -6,7 +6,7 @@
  * See: https://simplesamlphp.org/docs/stable/simplesamlphp-reference-idp-hosted
  */
 
-$metadata['__DYNAMIC:1__'] = [
+$metadata['urn:x-simplesamlphp:idp'] = [
     /*
      * The hostname of the server (VHOST) that will use this SAML entity.
      *
diff --git a/modules/admin/src/Controller/Federation.php b/modules/admin/src/Controller/Federation.php
index 6b8e08a15ea84bc316d18a7df34c5b89257fd183..43cbb00fa2b50f37ce0c44c40c57446b786d3d5c 100644
--- a/modules/admin/src/Controller/Federation.php
+++ b/modules/admin/src/Controller/Federation.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace SimpleSAML\Module\admin\Controller;
 
 use Exception;
+use SAML2\Constants as C;
 use SimpleSAML\Assert\Assert;
 use SimpleSAML\Auth;
 use SimpleSAML\Configuration;
@@ -195,7 +196,7 @@ class Federation
                 $idps = $this->mdHandler->getList('saml20-idp-hosted');
                 $saml2entities = [];
                 $httpUtils = new Utils\HTTP();
-                $metadataBase = $httpUtils->getBaseURL() . 'saml2/idp/metadata.php';
+                $metadataBase = Module::getModuleURL('saml/idp/metadata');
                 if (count($idps) > 1) {
                     foreach ($idps as $index => $idp) {
                         $idp['url'] = $metadataBase . '?idpentityid=' . urlencode($idp['entityid']);
@@ -213,6 +214,13 @@ class Federation
                 }
 
                 foreach ($saml2entities as $index => $entity) {
+                    Assert::validURI($entity['entityid']);
+                    Assert::maxLength(
+                        $entity['entityid'],
+                        C::SAML2INT_ENTITYID_MAX_LENGTH,
+                        sprintf('The entityID cannot be longer than %d characters.', C::SAML2INT_ENTITYID_MAX_LENGTH)
+                    );
+
                     $builder = new SAMLBuilder($entity['entityid']);
                     $builder->addMetadataIdP20($entity['metadata_array']);
                     $builder->addOrganizationInfo($entity['metadata_array']);
@@ -252,6 +260,13 @@ class Federation
                 }
 
                 foreach ($adfsentities as $index => $entity) {
+                    Assert::validURI($entity['entityid']);
+                    Assert::maxLength(
+                        $entity['entityid'],
+                        C::SAML2INT_ENTITYID_MAX_LENGTH,
+                        sprintf('The entityID cannot be longer than %d characters.', C::SAML2INT_ENTITYID_MAX_LENGTH)
+                    );
+
                     $builder = new SAMLBuilder($entity['entityid']);
                     $builder->addSecurityTokenServiceType($entity['metadata_array']);
                     $builder->addOrganizationInfo($entity['metadata_array']);
diff --git a/modules/core/docs/authproc_targetedid.md b/modules/core/docs/authproc_targetedid.md
index a73fbd4a4c99a7bdd66dbaf20f807f46459016a2..deb00c725499af42be9d36c73625ce2e8bba741b 100644
--- a/modules/core/docs/authproc_targetedid.md
+++ b/modules/core/docs/authproc_targetedid.md
@@ -34,7 +34,7 @@ A custom attribute:
 Internet2 compatible `eduPersontargetedID`:
 
     /* In saml20-idp-hosted.php. */
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:example-idp'] = [
         'host' => '__DEFAULT__',
         'auth' => 'example-static',
 
diff --git a/modules/saml/docs/keyrollover.md b/modules/saml/docs/keyrollover.md
index 0bc9891bb690ff7aad5581f3d0abba7ef9623659..e211960c8619a4b7668b1d796c7b4b935240436a 100644
--- a/modules/saml/docs/keyrollover.md
+++ b/modules/saml/docs/keyrollover.md
@@ -48,7 +48,7 @@ In `config/authsources.php`:
 
 In `metadata/saml20-idp-hosted.php`:
 
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:idp'] = [
         'host' => '__DEFAULT__',
         'auth' => 'example-userpass',
         'privatekey' => 'old.pem',
@@ -96,7 +96,7 @@ In `config/authsources.php`:
 
 In `metadata/saml20-idp-hosted.php`:
 
-    $metadata['__DYNAMIC:1__'] = [
+    $metadata['urn:x-simplesamlphp:idp'] = [
         'host' => '__DEFAULT__',
         'auth' => 'example-userpass',
         'certificate' => 'new.crt',
diff --git a/modules/saml/src/Auth/Source/SP.php b/modules/saml/src/Auth/Source/SP.php
index 3eef0d97ee3120e7397d300ee0e2a912668ee1dc..9e0f5882d7ca901f77b289e412eec5c6a5b91ab5 100644
--- a/modules/saml/src/Auth/Source/SP.php
+++ b/modules/saml/src/Auth/Source/SP.php
@@ -81,19 +81,20 @@ class SP extends \SimpleSAML\Auth\Source
         // Call the parent constructor first, as required by the interface
         parent::__construct($info, $config);
 
-        if (!isset($config['entityID'])) {
-            $config['entityID'] = $this->getMetadataURL();
-        }
-
-        /* For compatibility with code that assumes that $metadata->getString('entityid')
-         * gives the entity id. */
-        $config['entityid'] = $config['entityID'];
-
         $this->metadata = Configuration::loadFromArray(
             $config,
             'authsources[' . var_export($this->authId, true) . ']'
         );
-        $this->entityId = $this->metadata->getString('entityID');
+
+        $entityId = $this->metadata->getString('entityID');
+        Assert::validURI($entityId);
+        Assert::maxLength(
+            $entityId,
+            Constants::SAML2INT_ENTITYID_MAX_LENGTH,
+            sprintf('The entityID cannot be longer than %d characters.', Constants::SAML2INT_ENTITYID_MAX_LENGTH)
+        );
+
+        $this->entityId = $entityId;
         $this->idp = $this->metadata->getOptionalString('idp', null);
         $this->discoURL = $this->metadata->getOptionalString('discoURL', null);
         $this->disable_scoping = $this->metadata->getOptionalBoolean('disable_scoping', false);
@@ -107,7 +108,7 @@ class SP extends \SimpleSAML\Auth\Source
      */
     public function getMetadataURL(): string
     {
-        return Module::getModuleURL('saml/sp/metadata.php/' . urlencode($this->authId));
+        return Module::getModuleURL('saml/sp/metadata/' . urlencode($this->authId));
     }
 
 
diff --git a/modules/saml/src/Message.php b/modules/saml/src/Message.php
index bc07d81cee5cb92cf51ef12b925a4bdaa0ea3f39..388d1d6aebcafdaf49a499f41e054d5ee7f37db4 100644
--- a/modules/saml/src/Message.php
+++ b/modules/saml/src/Message.php
@@ -495,7 +495,7 @@ class Message
         // Shoaib: setting the appropriate binding based on parameter in sp-metadata defaults to HTTP_POST
         $ar->setProtocolBinding($protbind);
         $issuer = new Issuer();
-        $issuer->setValue($spMetadata->getString('entityid'));
+        $issuer->setValue($spMetadata->getString('entityID'));
         $ar->setIssuer($issuer);
         $ar->setAssertionConsumerServiceIndex(
             $spMetadata->getOptionalInteger('AssertionConsumerServiceIndex', null)
@@ -534,7 +534,7 @@ class Message
     ): LogoutRequest {
         $lr = new LogoutRequest();
         $issuer = new Issuer();
-        $issuer->setValue($srcMetadata->getString('entityid'));
+        $issuer->setValue($srcMetadata->getString('entityID'));
         $issuer->setFormat(Constants::NAMEID_ENTITY);
         $lr->setIssuer($issuer);
 
diff --git a/src/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php b/src/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
index 45bae13548aff54c3352b1ed1f1b0a495b1e5990..042dfa477da4ffc8af2aeecbc41ba851226dd772 100644
--- a/src/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
+++ b/src/SimpleSAML/Metadata/MetaDataStorageHandlerFlatFile.php
@@ -124,7 +124,7 @@ class MetaDataStorageHandlerFlatFile extends MetaDataStorageSource
 
         // add the entity id of an entry to each entry in the metadata
         foreach ($metadataSet as $entityId => &$entry) {
-            $entry = $this->updateEntityID($set, $entityId, $entry);
+            $entry['entityID'] = $entityId;
         }
 
         $this->cachedMetadata[$set] = $metadataSet;
diff --git a/src/SimpleSAML/Metadata/MetaDataStorageHandlerPdo.php b/src/SimpleSAML/Metadata/MetaDataStorageHandlerPdo.php
index bbd5d99e3a7b2c8d1dcd11b77d2cf7901659e1d4..c84408f25c337c1c03fb0620e231eb3db756b0fb 100644
--- a/src/SimpleSAML/Metadata/MetaDataStorageHandlerPdo.php
+++ b/src/SimpleSAML/Metadata/MetaDataStorageHandlerPdo.php
@@ -96,7 +96,7 @@ class MetaDataStorageHandlerPdo extends MetaDataStorageSource
                     throw new Error\Exception("Cannot decode metadata for entity '${d['entity_id']}'");
                 }
                 if (!array_key_exists('entityid', $data)) {
-                    $data['entityid'] = $d['entity_id'];
+                    $data['entityID'] = $d['entity_id'];
                 }
                 $metadata[$d['entity_id']] = $data;
             }
@@ -129,7 +129,7 @@ class MetaDataStorageHandlerPdo extends MetaDataStorageSource
         }
 
         foreach ($metadataSet as $entityId => &$entry) {
-            $entry = $this->updateEntityID($set, $entityId, $entry);
+            $entry['entityID'] = $entityId;
         }
 
         $this->cachedMetadata[$set] = $metadataSet;
@@ -159,24 +159,10 @@ class MetaDataStorageHandlerPdo extends MetaDataStorageSource
         }
 
         $tableName = $this->getTableName($set);
-
-        // according to the docs, it looks like *-idp-hosted metadata are the types
-        // that allow the __DYNAMIC:*__ entity id.  with the current table design
-        // we need to lookup the specific metadata entry but also we need to lookup
-        // any dynamic entries to see if the dynamic hosted entity id matches
-        if (substr($set, -10) == 'idp-hosted') {
-            $stmt = $this->db->read(
-                "SELECT entity_id, entity_data FROM {$tableName} "
-                . "WHERE (entity_id LIKE :dynamicId OR entity_id = :entityId)",
-                ['dynamicId' => '__DYNAMIC%', 'entityId' => $entityId]
-            );
-        } else {
-            // other metadata types should be able to match on entity id
-            $stmt = $this->db->read(
-                "SELECT entity_id, entity_data FROM {$tableName} WHERE entity_id = :entityId",
-                ['entityId' => $entityId]
-            );
-        }
+        $stmt = $this->db->read(
+            "SELECT entity_id, entity_data FROM {$tableName} WHERE entity_id = :entityId",
+            ['entityId' => $entityId]
+        );
 
         // throw pdo exception upon execution failure
         if (!$stmt->execute()) {
diff --git a/src/SimpleSAML/Metadata/MetaDataStorageSource.php b/src/SimpleSAML/Metadata/MetaDataStorageSource.php
index 2d3fc0246ec857409df66637fd2ebc69b18eba41..b22b5aaef4e51e0ad3c9b1a8a408643b24087869 100644
--- a/src/SimpleSAML/Metadata/MetaDataStorageSource.php
+++ b/src/SimpleSAML/Metadata/MetaDataStorageSource.php
@@ -346,32 +346,4 @@ abstract class MetaDataStorageSource
             throw new \Exception('Can not generate dynamic EntityID for metadata of this type: [' . $set . ']');
         }
     }
-
-
-    /**
-     * Updates the metadata entry's entity id and returns the modified array.  If the entity id is __DYNAMIC:*__ a
-     * the current url is assigned.  If it is explicit the entityid array key is updated to the entityId that was
-     * provided.
-     *
-     * @param string $metadataSet a metadata set (saml20-idp-hosted, saml20-sp-remote, etc)
-     * @param string $entityId the entity id we are modifying
-     * @param array $metadataEntry the fully populated metadata entry
-     * @return array modified metadata to include the valid entityid
-     *
-     * @throws \Exception
-     */
-    protected function updateEntityID(string $metadataSet, string $entityId, array $metadataEntry): array
-    {
-        $modifiedMetadataEntry = $metadataEntry;
-
-        // generate a dynamic hosted url
-        if (preg_match('/__DYNAMIC(:[0-9]+)?__/', $entityId)) {
-            $modifiedMetadataEntry['entityid'] = $this->getDynamicHostedUrl($metadataSet);
-        } else {
-            // set the entityid metadata array key to the provided entity id
-            $modifiedMetadataEntry['entityid'] = $entityId;
-        }
-
-        return $modifiedMetadataEntry;
-    }
 }
diff --git a/tests/modules/admin/src/Controller/FederationTest.php b/tests/modules/admin/src/Controller/FederationTest.php
index 417834bd7946b8941ba6bd626ab74e79d1e6698e..416d4dae27d2a348bf6f849ede5ad55759d51257 100644
--- a/tests/modules/admin/src/Controller/FederationTest.php
+++ b/tests/modules/admin/src/Controller/FederationTest.php
@@ -163,7 +163,7 @@ class FederationTest extends TestCase
                             'name' => [
                                 'en' => 'A service',
                             ],
-                            'entityID' => null,
+                            'entityID' => 'urn:x-simplesamlphp:example-sp',
                             'privatekey' => FederationTest::CERT_KEY,
                             'certificate' => FederationTest::CERT_PUBLIC,
                             'attributes' => ['uid', 'mail']
diff --git a/tests/modules/saml/src/Auth/Source/SPTest.php b/tests/modules/saml/src/Auth/Source/SPTest.php
index 772f04d86586e9c57c371dc2c5667816fcbcad93..66868cdc1caa209fe848558bccc49b26c989a349 100644
--- a/tests/modules/saml/src/Auth/Source/SPTest.php
+++ b/tests/modules/saml/src/Auth/Source/SPTest.php
@@ -122,7 +122,7 @@ class SPTest extends ClearStateTestCase
     private function createAuthnRequest(array $state = []): AuthnRequest
     {
         $info = ['AuthId' => 'default-sp'];
-        $config = [];
+        $config = ['entityID' => 'urn:x-simplesamlphp:example-sp'];
         $as = new SpTester($info, $config);
 
         /** @var \SAML2\AuthnRequest $ar */
@@ -149,7 +149,7 @@ class SPTest extends ClearStateTestCase
     private function createLogoutRequest(array $state = []): LogoutRequest
     {
         $info = ['AuthId' => 'default-sp'];
-        $config = ['entityID' => 'https://engine.surfconext.nl/authentication/idp/metadata'];
+        $config = ['entityID' => 'urn:x-simplesamlphp:example-sp'];
         $as = new SpTester($info, $config);
 
         /** @var \SAML2\LogoutRequest $lr */
@@ -184,7 +184,7 @@ class SPTest extends ClearStateTestCase
 
         $q = Utils::xpQuery($xml, '/samlp:AuthnRequest/saml:Issuer');
         $this->assertEquals(
-            'http://localhost/simplesaml/module.php/saml/sp/metadata.php/default-sp',
+            'urn:x-simplesamlphp:example-sp',
             $q[0]->textContent
         );
     }
@@ -293,7 +293,7 @@ class SPTest extends ClearStateTestCase
         ];
 
         $info = ['AuthId' => 'default-sp'];
-        $config = [];
+        $config = ['entityID' => 'urn:x-simplesamlphp:example-sp'];
         $as = new SpTester($info, $config);
         $as->authenticate($state);
     }
@@ -319,6 +319,7 @@ class SPTest extends ClearStateTestCase
 
         $info = ['AuthId' => 'default-sp'];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'idp' => 'https://engine.surfconext.nl/authentication/idp/metadata'
         ];
         $as = new SpTester($info, $config);
@@ -345,6 +346,7 @@ class SPTest extends ClearStateTestCase
 
         $info = ['AuthId' => 'default-sp'];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'idp' => $entityId
         ];
         $as = new SpTester($info, $config);
@@ -385,7 +387,7 @@ class SPTest extends ClearStateTestCase
         ];
 
         $info = ['AuthId' => 'default-sp'];
-        $config = [];
+        $config = ['entityID' => 'urn:x-simplesamlphp:example-sp'];
         $as = new SpTester($info, $config);
         try {
             $as->authenticate($state);
@@ -430,6 +432,7 @@ class SPTest extends ClearStateTestCase
 
         $info = ['AuthId' => 'default-sp'];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             // Use a url that is invalid for http redirects so redirect code throws an error
             // otherwise it will call exit
             'discoURL' => 'smtp://invalidurl'
@@ -447,12 +450,12 @@ class SPTest extends ClearStateTestCase
     {
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
-        $config = [];
+        $config = ['entityID' => 'urn:x-simplesamlphp:example-sp'];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
         $this->assertEquals('saml20-sp-remote', $md['metadata-set']);
-        $this->assertEquals('http://localhost/simplesaml/module.php/saml/sp/metadata.php/' . $spId, $md['entityid']);
+        $this->assertEquals('urn:x-simplesamlphp:example-sp', $md['entityid']);
         $this->assertArrayHasKey('SingleLogoutService', $md);
         $this->assertIsArray($md['SingleLogoutService']);
         $this->assertArrayHasKey('AssertionConsumerService', $md);
@@ -506,6 +509,7 @@ class SPTest extends ClearStateTestCase
     {
         $info = ['AuthId' => 'default-sp'];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'IDPList' => ['https://scope.example.com']
         ];
         $as = new SpTester($info, $config);
@@ -541,7 +545,7 @@ class SPTest extends ClearStateTestCase
         if (isset($stateIdpList)) {
             $state['IDPList'] = $stateIdpList;
         }
-        $config = [];
+        $config = ['entityID' => 'urn:x-simplesamlphp:example-sp'];
         if (isset($remoteMetadata)) {
             $config['IDPList'] = $remoteMetadata;
         }
@@ -622,25 +626,28 @@ class SPTest extends ClearStateTestCase
     {
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
-        $config = ['contacts' => [
-            [
-               'contactType'       => 'other',
-               'emailAddress'      => 'csirt@example.com',
-               'surName'           => 'CSIRT',
-               'telephoneNumber'   => '+31SECOPS',
-               'company'           => 'Acme Inc',
-               'attributes'        => [
-                   'xmlns:remd'        => 'http://refeds.org/metadata',
-                   'remd:contactType'  => 'http://refeds.org/metadata/contactType/security',
-               ],
-            ],
-            [
-               'contactType'       => 'administrative',
-               'emailAddress'      => 'j.doe@example.edu',
-               'givenName'         => 'Jane',
-               'surName'           => 'Doe',
-            ],
-        ]];
+        $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'contacts' => [
+                [
+                    'contactType'       => 'other',
+                    'emailAddress'      => 'csirt@example.com',
+                    'surName'           => 'CSIRT',
+                    'telephoneNumber'   => '+31SECOPS',
+                    'company'           => 'Acme Inc',
+                    'attributes'        => [
+                        'xmlns:remd'        => 'http://refeds.org/metadata',
+                        'remd:contactType'  => 'http://refeds.org/metadata/contactType/security',
+                    ],
+                ],
+                [
+                    'contactType'       => 'administrative',
+                    'emailAddress'      => 'j.doe@example.edu',
+                    'givenName'         => 'Jane',
+                    'surName'           => 'Doe',
+                ],
+            ]
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -683,14 +690,17 @@ class SPTest extends ClearStateTestCase
 
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
-        $config = ['contacts' => [
-            [
-               'contactType'       => 'technical',
-               'emailAddress'      => 'j.doe@example.edu',
-               'givenName'         => 'Jane',
-               'surName'           => 'Doe',
-            ],
-        ]];
+        $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'contacts' => [
+                [
+                    'contactType'       => 'technical',
+                    'emailAddress'      => 'j.doe@example.edu',
+                    'givenName'         => 'Jane',
+                    'surName'           => 'Doe',
+                ],
+            ]
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -725,13 +735,16 @@ class SPTest extends ClearStateTestCase
 
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
-        $config = ['contacts' => [
-            [
-               'contactType'       => 'technical',
-               'emailAddress'      => 'j.doe@example.edu',
-               'surName'           => 'Doe',
-            ],
-        ]];
+        $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'contacts' => [
+                [
+                    'contactType'       => 'technical',
+                    'emailAddress'      => 'j.doe@example.edu',
+                    'surName'           => 'Doe',
+                ],
+            ]
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -746,14 +759,17 @@ class SPTest extends ClearStateTestCase
     {
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
-        $config = ['contacts' => [
-            [
-               'contactType'       => 'anything',
-               'emailAddress'      => 'j.doe@example.edu',
-               'givenName'         => 'Jane',
-               'surName'           => 'Doe',
-            ],
-        ]];
+        $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'contacts' => [
+                [
+                   'contactType'       => 'anything',
+                   'emailAddress'      => 'j.doe@example.edu',
+                   'givenName'         => 'Jane',
+                   'surName'           => 'Doe',
+                ],
+            ]
+        ];
         $as = new SpTester($info, $config);
 
         $this->expectException(InvalidArgumentException::class);
@@ -769,17 +785,18 @@ class SPTest extends ClearStateTestCase
     {
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
-        $config = ['contacts' =>
-                [
+        $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'contacts' => [
                 [
                     'contactType'       => 'administrative',
                     'emailAddress'      => 'j.doe@example.edu',
                     'givenName'         => 'Jane',
                     'surName'           => 'Doe',
                 ],
-                ],
-                'acs.Bindings' => ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'],
-            ];
+            ],
+            'acs.Bindings' => ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -797,17 +814,18 @@ class SPTest extends ClearStateTestCase
     {
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
-        $config = ['contacts' =>
-                [
+        $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'contacts' => [
                 [
                     'contactType'       => 'administrative',
                     'emailAddress'      => 'j.doe@example.edu',
                     'givenName'         => 'Jane',
                     'surName'           => 'Doe',
                 ],
-                ],
-                'acs.Bindings' => ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', 'urn:this:doesnotexist'],
-            ];
+            ],
+            'acs.Bindings' => ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', 'urn:this:doesnotexist'],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -826,8 +844,9 @@ class SPTest extends ClearStateTestCase
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
         $config = [
-                'SingleLogoutServiceBinding' => ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'],
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'SingleLogoutServiceBinding' => ['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -846,8 +865,9 @@ class SPTest extends ClearStateTestCase
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
         $config = [
-                'SingleLogoutServiceBinding' => [],
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'SingleLogoutServiceBinding' => [],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -862,6 +882,7 @@ class SPTest extends ClearStateTestCase
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'SingleLogoutServiceBinding' => [
                 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
                 'urn:this:doesnotexist'
@@ -886,6 +907,7 @@ class SPTest extends ClearStateTestCase
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'SingleLogoutServiceBinding' => [
                 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
                 'urn:this:doesnotexist'
@@ -913,6 +935,7 @@ class SPTest extends ClearStateTestCase
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'AssertionConsumerService' => [
                 [
                     'index' => 1,
@@ -926,7 +949,7 @@ class SPTest extends ClearStateTestCase
                     'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
                 ],
             ],
-            ];
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -958,10 +981,11 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'WantAssertionsSigned' => true,
-                'redirect.sign' => true,
-                'sign.authnrequest' => true,
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'WantAssertionsSigned' => true,
+            'redirect.sign' => true,
+            'sign.authnrequest' => true,
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -972,10 +996,11 @@ class SPTest extends ClearStateTestCase
         $this->assertArrayNotHasKey('validate.authnrequest', $md);
 
         $config = [
-                'WantAssertionsSigned' => false,
-                'redirect.sign' => false,
-                'sign.authnrequest' => false,
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'WantAssertionsSigned' => false,
+            'redirect.sign' => false,
+            'sign.authnrequest' => false,
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -986,8 +1011,9 @@ class SPTest extends ClearStateTestCase
         $this->assertArrayNotHasKey('validate.authnrequest', $md);
 
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'sign.authnrequest' => true,
-            ];
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1005,12 +1031,13 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'RegistrationInfo' => [
-                    'authority' => 'urn:mace:sp.example.org',
-                    'instant' => '2008-01-17T11:28:03.577Z',
-                    'policies' => ['en' => 'http://sp.example.org/policy', 'es' => 'http://sp.example.org/politica'],
-                ],
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'RegistrationInfo' => [
+                'authority' => 'urn:mace:sp.example.org',
+                'instant' => '2008-01-17T11:28:03.577Z',
+                'policies' => ['en' => 'http://sp.example.org/policy', 'es' => 'http://sp.example.org/politica'],
+            ],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1033,8 +1060,12 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-            'NameIDPolicy' => [ 'Format' => 'urn:mace:shibboleth:1.0:nameIdentifier', 'AllowCreate' => true ],
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'NameIDPolicy' => [
+                'Format' => 'urn:mace:shibboleth:1.0:nameIdentifier',
+                'AllowCreate' => true
+            ],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1051,8 +1082,9 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'NameIDPolicy' => 'urn:mace:shibboleth:1.0:nameIdentifier',
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'NameIDPolicy' => 'urn:mace:shibboleth:1.0:nameIdentifier',
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1069,8 +1101,9 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'NameIDPolicy' => ['AllowCreate' => true],
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'NameIDPolicy' => ['AllowCreate' => true],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1087,19 +1120,20 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'OrganizationName' => [
-                    'en' => 'Voorbeeld Organisatie Foundation b.a.',
-                    'nl' => 'Stichting Voorbeeld Organisatie b.a.',
-                ],
-                'OrganizationDisplayName' => [
-                    'en' => 'Example organization',
-                    'nl' => 'Voorbeeldorganisatie',
-                ],
-                'OrganizationURL' => [
-                    'en' => 'https://example.com',
-                    'nl' => 'https://example.com/nl',
-                ],
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'OrganizationName' => [
+                'en' => 'Voorbeeld Organisatie Foundation b.a.',
+                'nl' => 'Stichting Voorbeeld Organisatie b.a.',
+            ],
+            'OrganizationDisplayName' => [
+                'en' => 'Example organization',
+                'nl' => 'Voorbeeldorganisatie',
+            ],
+            'OrganizationURL' => [
+                'en' => 'https://example.com',
+                'nl' => 'https://example.com/nl',
+            ],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1117,13 +1151,14 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'OrganizationName' => [
-                    'nl' => 'Stichting Voorbeeld Organisatie b.a.',
-                ],
-                'OrganizationURL' => [
-                    'nl' => 'https://example.com/nl',
-                ],
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'OrganizationName' => [
+                'nl' => 'Stichting Voorbeeld Organisatie b.a.',
+            ],
+            'OrganizationURL' => [
+                'nl' => 'https://example.com/nl',
+            ],
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1141,13 +1176,14 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'OrganizationName' => [
-                    'nl' => 'Stichting Voorbeeld Organisatie b.a.',
-                ],
-                'OrganizationDisplayName' => [
-                    'nl' => 'Voorbeeldorganisatie',
-                ],
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'OrganizationName' => [
+                'nl' => 'Stichting Voorbeeld Organisatie b.a.',
+            ],
+            'OrganizationDisplayName' => [
+                'nl' => 'Voorbeeldorganisatie',
+            ],
+        ];
         $as = new SpTester($info, $config);
 
         $this->expectException(Exception::class);
@@ -1164,6 +1200,7 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'UIInfo' => [
                 'DisplayName' => [
                     'en' => 'English name',
@@ -1174,7 +1211,7 @@ class SPTest extends ClearStateTestCase
                     'es' => 'Descripción en Español'
                  ],
             ],
-            ];
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1193,8 +1230,9 @@ class SPTest extends ClearStateTestCase
 
         $ea = ['{urn:simplesamlphp:v1}foo' => ['bar']];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'EntityAttributes' => $ea,
-            ];
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1211,6 +1249,7 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'name' => [
                 'en' => 'My First SP',
             ],
@@ -1224,7 +1263,7 @@ class SPTest extends ClearStateTestCase
             'attributes.required' => [
                 'eduPersonPrincipalName' => 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6',
             ],
-            ];
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1233,14 +1272,20 @@ class SPTest extends ClearStateTestCase
         $this->assertArrayHasKey('description', $md);
         $this->assertEquals('This SP is my first one', $md['description']['en']);
         $this->assertArrayHasKey('attributes', $md);
-        $this->assertEquals([
+        $this->assertEquals(
+            [
                 'mail' => 'urn:oid:0.9.2342.19200300.100.1.3',
                 'schacHomeOrganization' => 'urn:oid:1.3.6.1.4.1.25178.1.2.9',
-            ], $md['attributes']);
+            ],
+            $md['attributes']
+        );
         $this->assertArrayHasKey('attributes.required', $md);
-        $this->assertEquals([
+        $this->assertEquals(
+            [
                 'eduPersonPrincipalName' => 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6',
-            ], $md['attributes.required']);
+            ],
+            $md['attributes.required']
+        );
     }
 
     /**
@@ -1252,13 +1297,14 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'name' => [
                 'en' => 'My First SP',
             ],
             'description' => [
                 'en' => 'This SP is my first one',
             ],
-            ];
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1275,11 +1321,12 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'attributes' => [
                 'mail' => 'urn:oid:0.9.2342.19200300.100.1.3',
                 'schacHomeOrganization' => 'urn:oid:1.3.6.1.4.1.25178.1.2.9',
             ],
-            ];
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1295,6 +1342,7 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'name' => [
                 'en' => 'My First SP',
             ],
@@ -1323,8 +1371,9 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1349,9 +1398,10 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'privatekey' => self::CERT_KEY,
-                'certificate' => self::CERT_PUBLIC,
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'privatekey' => self::CERT_KEY,
+            'certificate' => self::CERT_PUBLIC,
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1374,11 +1424,12 @@ class SPTest extends ClearStateTestCase
         $info = ['AuthId' => $spId];
 
         $config = [
-                'privatekey' => self::CERT_KEY,
-                'certificate' => self::CERT_PUBLIC,
-                'new_privatekey' => self::CERT_OTHER_KEY,
-                'new_certificate' => self::CERT_OTHER_PUBLIC,
-            ];
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
+            'privatekey' => self::CERT_KEY,
+            'certificate' => self::CERT_PUBLIC,
+            'new_privatekey' => self::CERT_OTHER_KEY,
+            'new_certificate' => self::CERT_OTHER_PUBLIC,
+        ];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1404,7 +1455,7 @@ class SPTest extends ClearStateTestCase
     {
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
-        $config = [];
+        $config = ['entityID' => 'urn:x-simplesamlphp:example-sp'];
         $as = new SpTester($info, $config);
 
         $md = $as->getHostedMetadata();
@@ -1421,6 +1472,7 @@ class SPTest extends ClearStateTestCase
         $spId = 'myhosted-sp';
         $info = ['AuthId' => $spId];
         $config = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'AssertionConsumerService' => [
                 [
                     'index' => 1,
diff --git a/tests/modules/saml/src/Controller/ProxyTest.php b/tests/modules/saml/src/Controller/ProxyTest.php
index 66a59590679a79355a95c0c931471e6bd96c350a..27fe90ddaea0c96439af9238a53457de2c3e488c 100644
--- a/tests/modules/saml/src/Controller/ProxyTest.php
+++ b/tests/modules/saml/src/Controller/ProxyTest.php
@@ -45,7 +45,10 @@ class ProxyTest extends TestCase
         Configuration::setPreLoadedConfig(
             Configuration::loadFromArray(
                 [
-                    'phpunit' => ['saml:SP'],
+                    'phpunit' => [
+                        'saml:SP',
+                        'entityID' => 'urn:x-simplesamlphp:example-sp',
+                    ],
                 ],
                 '[ARRAY]',
                 'simplesaml'
diff --git a/tests/modules/saml/src/Controller/ServiceProviderTest.php b/tests/modules/saml/src/Controller/ServiceProviderTest.php
index d31deab11f2ed00efb66b89e92cc4a67a95abc84..7e50478845c815b3c13707add1cb2bcad3946530 100644
--- a/tests/modules/saml/src/Controller/ServiceProviderTest.php
+++ b/tests/modules/saml/src/Controller/ServiceProviderTest.php
@@ -57,7 +57,10 @@ class ServiceProviderTest extends TestCase
             Configuration::loadFromArray(
                 [
                     'admin' => ['core:AdminPassword'],
-                    'phpunit' => ['saml:SP'],
+                    'phpunit' => [
+                        'saml:SP',
+                        'entityID' => 'urn:x-simplesamlphp:example-sp',
+                    ],
                 ],
                 '[ARRAY]',
                 'simplesaml'
diff --git a/tests/src/SimpleSAML/Metadata/SAMLBuilderTest.php b/tests/src/SimpleSAML/Metadata/SAMLBuilderTest.php
index 4b262560fea51e14003ccc3e75840e7aaabf862a..c1602295a18e952efcdfb138b5eed3917be5ce37 100644
--- a/tests/src/SimpleSAML/Metadata/SAMLBuilderTest.php
+++ b/tests/src/SimpleSAML/Metadata/SAMLBuilderTest.php
@@ -396,6 +396,7 @@ class SAMLBuilderTest extends TestCase
     {
         $info = ['AuthId' => 'default-sp'];
         $metadata = [
+            'entityID' => 'urn:x-simplesamlphp:example-sp',
             'certificate' => '../' . self::SECURITY . '/certificates/rsa-pem/selfsigned.simplesamlphp.org.crt',
             'privatekey' => '../' . self::SECURITY . '/certificates/rsa-pem/selfsigned.simplesamlphp.org.key',
         ];