@@ -1829,6 +1829,67 @@ public function getVciStatusListKeyProfile(): StatusListKeyProfileEnum
18291829 }
18301830
18311831
1832+ /**
1833+ * Whether any configured Status List pool signs under the given key profile.
1834+ *
1835+ * Answered from the raw configured values rather than by building the pools, and that is the point
1836+ * of it. The JWKS endpoint asks this to decide whether the credential signing key still has to be
1837+ * published, and a pool misconfigured in any way at all would otherwise make the whole bag
1838+ * unreadable and the answer "no" - withdrawing the key that a different, perfectly good pool's
1839+ * already published tokens are verified through. A question about one pool must not be answerable
1840+ * only while every pool is valid.
1841+ *
1842+ * The pool bag asks it too, before resolving the issuer `did:web`, so that an option only the
1843+ * `did_web` profile reads is not consulted for a deployment which has no pool on it.
1844+ *
1845+ * A value which is not a valid profile at all counts as "no": the pool is about to be refused by
1846+ * name, which is a better error than one about whichever profile was being asked about.
1847+ *
1848+ * @param array<array-key,mixed> $pools
1849+ */
1850+ protected function isAnyStatusListPoolOnKeyProfileIn (
1851+ array $ pools ,
1852+ StatusListKeyProfileEnum $ keyProfile ,
1853+ StatusListKeyProfileEnum $ defaultKeyProfile ,
1854+ ): bool {
1855+ /** @var mixed $poolConfig */
1856+ foreach ($ pools as $ poolConfig ) {
1857+ if (!is_array ($ poolConfig ) || !array_key_exists (StatusListPool::KEY_KEY_PROFILE , $ poolConfig )) {
1858+ if ($ defaultKeyProfile === $ keyProfile ) {
1859+ return true ;
1860+ }
1861+
1862+ continue ;
1863+ }
1864+
1865+ /** @var mixed $configured */
1866+ $ configured = $ poolConfig [StatusListPool::KEY_KEY_PROFILE ];
1867+
1868+ if ($ configured === $ keyProfile || $ configured === $ keyProfile ->value ) {
1869+ return true ;
1870+ }
1871+ }
1872+
1873+ return false ;
1874+ }
1875+
1876+
1877+ /**
1878+ * Whether any configured Status List pool signs under the given key profile.
1879+ *
1880+ * @throws \SimpleSAML\Error\ConfigurationError On a malformed default key profile, which is the one
1881+ * value this cannot be answered without.
1882+ */
1883+ public function isAnyStatusListPoolOnKeyProfile (StatusListKeyProfileEnum $ keyProfile ): bool
1884+ {
1885+ return $ this ->isAnyStatusListPoolOnKeyProfileIn (
1886+ $ this ->config ()->getOptionalArray (self ::OPTION_VCI_STATUS_LIST_POOLS , []),
1887+ $ keyProfile ,
1888+ $ this ->getVciStatusListKeyProfile (),
1889+ );
1890+ }
1891+
1892+
18321893 /**
18331894 * The configured Status List pools.
18341895 *
@@ -1844,9 +1905,27 @@ public function getVciStatusListPoolBag(): StatusListPoolBag
18441905 return $ this ->vciStatusListPoolBag ;
18451906 }
18461907
1908+ $ pools = $ this ->config ()->getOptionalArray (self ::OPTION_VCI_STATUS_LIST_POOLS , []);
1909+ $ defaultKeyProfile = $ this ->getVciStatusListKeyProfile ();
1910+
18471911 $ poolBag = StatusListPoolBag ::fromConfig (
1848- $ this ->config ()->getOptionalArray (self ::OPTION_VCI_STATUS_LIST_POOLS , []),
1849- $ this ->getVciStatusListKeyProfile (),
1912+ $ pools ,
1913+ $ defaultKeyProfile ,
1914+ // The module wide issuer identity, which the `did_web` key profile stamps onto every list
1915+ // it creates. Taken from here rather than configured per pool, so that a deployment cannot
1916+ // end up with two issuer identities of which only one has a published DID document.
1917+ //
1918+ // Resolved only when some pool is actually on that profile. Reading it unconditionally
1919+ // would mean a malformed did:web identifier -- an option no other profile looks at -- also
1920+ // stopping the pools from being read, and the JWKS endpoint answers "does any pool need its
1921+ // key published?" by reading them. A pool on the `jwks` profile would then have the key its
1922+ // already published tokens are verified through quietly withdrawn, over a setting it does
1923+ // not use.
1924+ $ this ->isAnyStatusListPoolOnKeyProfileIn (
1925+ $ pools ,
1926+ StatusListKeyProfileEnum::DidWeb,
1927+ $ defaultKeyProfile ,
1928+ ) ? $ this ->getVciIssuerDidIdentifier () : null ,
18501929 );
18511930
18521931 $ supportedIds = $ this ->getVciCredentialConfigurationIdsSupported ();
0 commit comments