apereo/cas · warning
Skipped metadata SignatureValidationFilter since signature…
Error message
Skipped metadata SignatureValidationFilter since signature cannot be located for [{}] What it means
This is a WARN log from BaseSamlRegisteredServiceMetadataResolver.addSignatureValidationFilterIfNeeded, emitted when the service requests signature validation but no signature verification key/certificate can be located in its configuration. The SignatureValidationFilter is skipped entirely, so incoming metadata signatures are NOT verified for that service — a security-relevant downgrade. Metadata processing continues without signature enforcement.
Solutions
- Configure the signature verification certificate/key for the service (metadataSignatureValidationPublicKey or equivalent) in the service definition.
- Verify the key file path exists and is readable by the CAS process user.
- If using a keystore, confirm the alias and password resolve to a valid certificate.
- Re-save and reload the service, then confirm the DEBUG log 'Added metadata SignatureValidationFilter' appears.
- Do not ignore this warning in production if signed metadata is a security requirement; treat it as a misconfiguration.
Example fix
// before: signature validation requested but no key configured
{
"@class": "org.apereo.cas.support.saml.services.SamlRegisteredService",
"serviceId": "https://sp.example.org/metadata",
"requireSignedRoot": true
}
// after
{
"@class": "org.apereo.cas.support.saml.services.SamlRegisteredService",
"serviceId": "https://sp.example.org/metadata",
"requireSignedRoot": true,
"metadataSignatureValidationPublicKey": "file:/etc/cas/sp-signing.crt"
} Defensive patterns
Strategy: validation
Validate before calling
// Verify signing material exists before saving a service that requires signed metadata
String keyPath = service.getMetadataSignatureValidationPublicKey();
if (service.isRequireSignedRoot() && (keyPath == null || !new java.io.File(
new java.net.URI(keyPath.replace("file:", "")).getPath()).canRead())) {
throw new IllegalStateException("Signed metadata required but signing key missing/unreadable for " + service.getServiceId());
} Try / catch
try {
var resolver = baseResolver.buildMetadataResolver(service, metadataFilters);
} catch (Exception e) {
LOGGER.error("Failed to build metadata resolver with signature validation for {}", service.getServiceId(), e);
} Prevention
- Refuse to enable 'require signed metadata' on a service without uploading its verification certificate
- Check that certificate file paths are absolute and readable by the CAS runtime user
- After saving the service, confirm the DEBUG log 'Added metadata SignatureValidationFilter' appears
- Never dismiss this WARN in security-sensitive deployments; the filter being skipped means unsigned metadata is accepted
When it happens
Trigger: Building a metadata resolver for a SamlRegisteredService with metadata signature validation enabled (isSignatureValidated or require-signed-metadata), but the signature verification key property (e.g. metadataSignatureValidationPublicKey / keystore-based cert) is unset, blank, or unreadable, so the code takes the else branch.
Common situations: Operator enabled 'require signed metadata' but forgot to upload the IdP/SP signing certificate; key file path wrong or unreadable by the CAS process; certificate stored in a keystore alias that does not exist; service cloned from a template that left the signing cert field empty.
Related errors
- Request is not signed but should be
- Signing credentials for validation could not be resolved
- Signing credentials for validation could not be resolved…
- Logout request is not signed but should be for service
- Resource [ ] cannot be located
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/2a13f6b3f8cc58a1.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-saml-idp-metadata/src/main/java/org/apereo/cas/support/saml/services/idp/metadata/cache/resolver/BaseSamlRegisteredServiceMetadataResolver.java:128
filter.initialize();
metadataFilterList.add(filter);
LOGGER.debug("Added metadata predicate filter with direction [{}] and entity attribute conditions [{}]",
service.getMetadataCriteriaDirection(), conditions);
}
}
private static void addSignatureValidationFilterIfNeeded(final SamlRegisteredService service,
@Nullable final SignatureValidationFilter signatureValidationFilter,
final List<MetadataFilter> metadataFilterList) throws Exception {
if (signatureValidationFilter != null) {
if (!signatureValidationFilter.isInitialized()) {
signatureValidationFilter.setRequireSignedRoot(service.isRequireSignedRoot());
signatureValidationFilter.initialize();
}
metadataFilterList.add(signatureValidationFilter);
LOGGER.debug("Added metadata SignatureValidationFilter for [{}]", service.getServiceId());
} else {
LOGGER.warn("Skipped metadata SignatureValidationFilter since signature cannot be located for [{}]", service.getServiceId());
}
}
protected static void buildEntityDescriptorCertificatesExpirationFilterIfNeeded(
final SamlRegisteredService service,
final List<MetadataFilter> metadataFilterList) throws Exception {
if (service.isValidateMetadataCertificates()) {
val filter = new EntityDescriptorCertificatesExpirationFilter();
filter.initialize();
metadataFilterList.add(filter);
LOGGER.debug("Added EntityDescriptorCertificatesExpirationFilter for [{}]", service.getServiceId());
}
}
protected static void buildSignatureValidationFilterIfNeeded(final SamlRegisteredService service,
final List<MetadataFilter> metadataFilterList)
throws Exception {
if (StringUtils.isBlank(service.getMetadataSignatureLocation())) {View on GitHub (pinned to e7288fc434)