apereo/cas · error · RevokedCertificateException

All CRL entries have been revoked. Rejecting the first entry

Error message

All CRL entries have been revoked. Rejecting the first entry [{}]

What it means

Thrown as RevokedCertificateException when every non-expired CRL retrieved contains a revocation entry for the certificate (revokedCrls.size() == crls.size()). CAS rejects the certificate: the first matching revoked entry is logged and RevokedCertificateException(entry) is thrown, failing authentication for that X.509 credential.

Solutions

  1. Treat this as correct behavior: the certificate IS revoked; issue a new certificate for the user.
  2. Verify the revocation is legitimate by checking the CRL entry's revocation date and reason with 'openssl crl -in ca.crl -text'.
  3. Remove the revoked certificate from client keystores/browsers and redeploy the replacement cert.
  4. If revocation was in error, have the CA un-revoke/reissue — do not weaken the revocation policy.

Example fix

// before: still authenticating with old revoked cert
keytool -list -v -keystore client.p12
// after: replace with newly issued certificate
keytool -importkeystore -srckeystore new-client.p12 -destkeystore client.p12
Defensive patterns

Strategy: try-catch

Validate before calling

X509CRL crl = /* fetched */;
if (crl != null && crl.isRevoked(cert)) {
    throw new RevokedCertificateException(crl.getRevokedCertificate(cert));
}

Try / catch

try {
    checker.check(cert);
} catch (RevokedCertificateException e) {
    LOGGER.warn("Certificate [{}] is revoked as of [{}]",
        cert.getSerialNumber(), e.getMessage());
    throw e; // do not swallow: reject authentication
}

Prevention

When it happens

Trigger: AbstractCRLRevocationChecker.check() finds the certificate's serial number listed in each valid CRL — i.e. the cert was revoked by its CA (compromise, key loss, deliberate revocation).

Common situations: User presents a genuinely revoked client certificate after losing a smart card or leaving the organization; a test/old certificate revoked by the CA is still deployed in a keystore; multiple CRLs (e.g. from cascading CAs) all list the serial.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/c5327cf408be731b. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-x509-core/src/main/java/org/apereo/cas/adaptors/x509/authentication/revocation/checker/AbstractCRLRevocationChecker.java:88

        val expiredCrls = new ArrayList<X509CRL>(crls.size());
        crls.stream().filter(CertUtils::isExpired).forEach(crl -> {
            LOGGER.warn("CRL data expired on [{}]", crl.getNextUpdate());
            expiredCrls.add(crl);
        });

        if (crls.size() == expiredCrls.size()) {
            LOGGER.warn("All CRLs retrieved have expired. Applying CRL expiration policy...");
            for (val crl : expiredCrls) {
                this.expiredCRLPolicy.apply(crl);
            }
        } else {
            crls.removeAll(expiredCrls);
            LOGGER.debug("Valid CRLs [{}] found that are not expired yet", crls);

            val revokedCrls = crls.stream().map(crl -> crl.getRevokedCertificate(cert)).filter(Objects::nonNull).toList();
            if (revokedCrls.size() == crls.size()) {
                val entry = revokedCrls.getFirst();
                LOGGER.warn("All CRL entries have been revoked. Rejecting the first entry [{}]", entry);
                throw new RevokedCertificateException(entry);
            }
        }
    }

    /**
     * Records the addition of a new CRL entry.
     *
     * @param id  the id of the entry to keep track of
     * @param crl new CRL entry
     * @return true if the entry was added successfully.
     * @since 4.1
     */
    protected abstract boolean addCRL(Object id, X509CRL crl);

    /**
     * Gets the collection of CRLs for the given certificate.
     *

View on GitHub (pinned to e7288fc434)