@Bean
        @ConditionalOnMissingBean(name = "webAuthnMetadataService")
        @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
        @Lazy(false)
        public AttestationTrustSource webAuthnMetadataService(
            final ConfigurableApplicationContext applicationContext,
            final CasConfigurationProperties casProperties) {
            return BeanSupplier.of(AttestationTrustSource.class)
                .when(CONDITION.given(applicationContext.getEnvironment()))
                .supply(Unchecked.supplier(() -> {
                    val composite = new CompositeAttestationTrustSource();

                    val trustSource = casProperties.getAuthn().getMfa().getWebAuthn().getCore().getTrustSource();

                    val loc = trustSource.getTrustedDeviceMetadata().getLocation();
                    if (ResourceUtils.doesResourceExist(loc)) {
                        try (val is = loc.getInputStream()) {
                            LOGGER.debug("Loading FIDO trusted device metadata from location [{}]", loc);
                            val metadata = MetadataObject.readMetadata(is);
                            val jsonService = new YubicoJsonMetadataService(List.of(metadata));
                            composite.addAttestationTrustSource(jsonService);
                        }
                    }

                    val fidoProperties = trustSource.getFido();
                    if (StringUtils.isNotBlank(fidoProperties.getLegalHeader())
                        && StringUtils.isNotBlank(fidoProperties.getMetadataBlobUrl())
                        && StringUtils.isNotBlank(fidoProperties.getTrustRootUrl())) {
                        val trustRootUrl = new URI(fidoProperties.getTrustRootUrl()).toURL();
                        val trustRootUrlHashes = org.springframework.util.StringUtils.commaDelimitedListToSet(fidoProperties.getTrustRootHash())
                            .stream()
                            .map(Unchecked.function(ByteArray::fromHex))
                            .collect(Collectors.toSet());

                        val downloader = FidoMetadataDownloader.builder()
                            .expectLegalHeader(fidoProperties.getLegalHeader())
                            .downloadTrustRoot(trustRootUrl, trustRootUrlHashes)
                            .useTrustRootCacheFile(fidoProperties.getTrustRootCacheFile())
                            .downloadBlob(new URI(fidoProperties.getMetadataBlobUrl()).toURL())
                            .useBlobCacheFile(fidoProperties.getBlobCacheFile())
                            .verifyDownloadsOnly(true)
                            .clock(Clock.systemUTC())
                            .build();

                        LOGGER.info("You have chosen to accept the FIDO Alliance's legal terms & conditions for downloading metadata blobs");
                        LOGGER.info(fidoProperties.getLegalHeader());

                        LOGGER.debug("Starting to refresh/download FIDO metadata blob from [{}] and caching it at [{}]",
                            fidoProperties.getMetadataBlobUrl(), fidoProperties.getBlobCacheFile());
                        val blob = downloader.refreshBlob();
                        val fidoService = FidoMetadataService.builder()
                            .useBlob(blob)
                            .build();
                        composite.addAttestationTrustSource(fidoService);
                    }
                    return composite;
                }))
                .otherwiseProxy()
                .get();
        }
This is {@link WebAuthnConfiguration}.

@author Misagh Moayyed
@since 6.1.0
support/cas-server-support-webauthn/src/main/java/org/apereo/cas/config/WebAuthnConfiguration.java