apereo/cas · error · FailedLoginException

Certificate keyUsage constraint forbids SSL client…

Error message

Certificate keyUsage constraint forbids SSL client authentication.

What it means

When checkKeyUsage is enabled, X509CredentialsAuthenticationHandler.validate() verifies that an end-entity certificate's keyUsage extension permits SSL/TLS client authentication. If isValidKeyUsage() finds the required bits absent (or the extension missing), it throws FailedLoginException.

Solutions

  1. Set cas.authn.x509.check-key-usage=false if your PKI does not populate keyUsage for client certs.
  2. Re-issue the client certificate with keyUsage including digitalSignature (plus keyEncipherment as appropriate for TLS client auth).
  3. Use a certificate explicitly issued for client authentication.
  4. Inspect the cert with: openssl x509 -in cert.pem -noout -ext keyUsage.

Example fix

// before
cas.authn.x509.check-key-usage=true
// after
cas.authn.x509.check-key-usage=false
Defensive patterns

Strategy: validation

Validate before calling

boolean[] ku = cert.getKeyUsage();
boolean ok = ku != null && ((ku[0] /* digitalSignature */));
if (!ok) { reject("cert not usable for client auth"); }

Type guard

boolean supportsClientAuth(X509Certificate cert) {
    boolean[] ku = cert.getKeyUsage();
    return ku != null && ku.length > 0 && ku[0];
}

Try / catch

try {
    handler.authenticate(credential);
} catch (FailedLoginException e) {
    // keyUsage forbids client authentication: re-issue cert or relax checkKeyUsage
}

Prevention

When it happens

Trigger: cas.authn.x509.check-key-usage=true and the presented end-entity certificate's keyUsage bits do not satisfy the client-auth requirement (e.g. no digitalSignature/keyEncipherment bits).

Common situations: Certificates issued for serverAuth or code signing used as client certs; PKI re-issue dropping the digitalSignature bit; checkKeyUsage enabled while the CA issues certs without any keyUsage extension.

Understand the failure class

Related errors


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

Appendix: source

Thrown at support/cas-server-support-x509-core/src/main/java/org/apereo/cas/adaptors/x509/authentication/handler/support/X509CredentialsAuthenticationHandler.java:243

        LOGGER.warn("Either client certificate could not be determined, or a trusted issuer could not be located");
        throw new FailedLoginException();
    }

    private void validate(final X509Certificate cert) throws GeneralSecurityException {
        cert.checkValidity();
        this.revocationChecker.check(cert);

        val pathLength = cert.getBasicConstraints();
        if (pathLength < 0) {
            if (!isCertificateAllowed(cert)) {
                val msg = "Certificate subject does not match pattern " + this.regExSubjectDnPattern.pattern();
                LOGGER.error(msg);
                throw new FailedLoginException(msg);
            }
            if (this.checkKeyUsage && !isValidKeyUsage(cert)) {
                val msg = "Certificate keyUsage constraint forbids SSL client authentication.";
                LOGGER.error(msg);
                throw new FailedLoginException(msg);
            }
        } else {
            if (pathLength == Integer.MAX_VALUE && !this.maxPathLengthAllowUnspecified) {
                val msg = "Unlimited certificate path length not allowed by configuration.";
                LOGGER.error(msg);
                throw new FailedLoginException(msg);
            }
            if (pathLength > this.maxPathLength && pathLength < Integer.MAX_VALUE) {
                val msg = String.format("Certificate path length %s exceeds maximum value %s.", pathLength, this.maxPathLength);
                LOGGER.error(msg);
                throw new FailedLoginException(msg);
            }
        }
    }

    /**
     * Checks if is valid key usage. <p>
     * KeyUsage ::= BIT STRING { digitalSignature (0), nonRepudiation (1),

View on GitHub (pinned to e7288fc434)