apereo/cas · error · FilterException
Expired or invalid certificate in metadata for
Error message
Expired or invalid certificate in metadata for
What it means
Part of the metadata certificate expiration filter: for every X509 certificate found in an IdP entity descriptor, cert.checkValidity() is called. If the certificate is expired (NotAfter passed) or not yet valid (NotBefore in future) or otherwise unparsable, a FilterException is raised so bad metadata cannot be trusted.
Solutions
- Obtain updated metadata from the IdP containing valid certificates and refresh the cached copy.
- Set the system clock/timezone correctly on the CAS server.
- Temporarily remove the expiration filter from the filter chain if policy permits (and rotate certs promptly).
- Contact the IdP administrator to publish corrected metadata.
Example fix
// before <!-- metadata contains expired cert from 2023 --> // after <!-- refresh metadata so NotAfter is in the future, or re-import updated IdP metadata -->
Defensive patterns
Strategy: try-catch
Validate before calling
val cert = X509Support.decodeCertificate(certXml.getValue()); cert.checkValidity(); // throws CertificateException if expired or not-yet-valid
Type guard
boolean certIsValid(X509Certificate c) { try { c.checkValidity(); return true; } catch (CertificateException e) { return false; } } Try / catch
try {
filterChain.process(entityDescriptor, context);
} catch (FilterException e) {
LOGGER.warn("Metadata rejected: {}", e.getMessage());
metrics.increment("saml.metadata.certExpired");
} Prevention
- Monitor certificate NotAfter dates in trusted IdP metadata and alert before expiry.
- Refresh metadata on a schedule from the IdP's published source.
- Keep CAS server clocks NTP-synced.
- Test certificate rotation procedures with IdP partners.
When it happens
Trigger: Running the metadata filters pipeline over metadata containing an X509Certificate whose validity window does not include the current time, or a value that cannot be decoded into a certificate (decodeCertificate succeeds but checkValidity, or decoding itself, throws CertificateException).
Common situations: IdP rotated its signing certificate and old expired cert still present in metadata; CAS clock skew or wrong system time; stale cached metadata file; self-signed test cert past expiry.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- No Certificates provided
- Unable to resolve the encryption [public] key for entity id
- Unable to accept certificate
- Public and private keys do not match
- Configuration element indicated an entityCertificate, but…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/ab6f6c748d5ba4de.
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/filter/EntityDescriptorCertificatesExpirationFilter.java:43
@Override
public XMLObject filter(@Nullable final XMLObject metadata,
@NonNull final MetadataFilterContext context) throws FilterException {
if (metadata instanceof final EntityDescriptor ed) {
for (val role : ed.getRoleDescriptors()) {
for (val kd : role.getKeyDescriptors()) {
val ki = kd.getKeyInfo();
for (val x509 : ki.getX509Datas()) {
for (val xmlCert : x509.getX509Certificates()) {
try {
val cert = X509Support.decodeCertificate(xmlCert.getValue());
LOGGER.debug("Evaluating certificate [{}] in metadata for [{}]. Not Before [{}], Not After [{}]",
cert.getSubjectX500Principal().getName(), ed.getEntityID(), cert.getNotBefore(), cert.getNotAfter());
cert.checkValidity();
} catch (final CertificateException e) {
LoggingUtils.error(LOGGER, e);
throw new FilterException("Expired or invalid certificate in metadata for " + ed.getEntityID());
}
}
}
}
}
}
return metadata;
}
}
View on GitHub (pinned to e7288fc434)