apereo/cas · error · FailedLoginException

Certificate path length

Error message

Certificate path length %s exceeds maximum value %s.

What it means

X509CredentialsAuthenticationHandler.validate() compares a CA certificate's basicConstraints pathLenConstraint with the configured maxPathLength. A finite path length exceeding the configured maximum makes the chain too deep and validation throws FailedLoginException.

Solutions

  1. Increase cas.authn.x509.max-path-length to at least the number of intermediate CA levels in your hierarchy.
  2. Flatten the PKI so client certs are issued from a shallower CA path.
  3. Inspect chain depth with: openssl x509 -in cert.pem -noout -text | grep pathlen.
  4. If chains are legitimately unbounded, combine with max-path-length-allow-unspecified=true.

Example fix

// before
cas.authn.x509.max-path-length=1
// after
cas.authn.x509.max-path-length=5
Defensive patterns

Strategy: validation

Validate before calling

int pl = cert.getBasicConstraints();
if (pl >= 0 && pl > configuredMaxPathLength) { reject("CA chain deeper than configured max"); }

Type guard

boolean withinMaxPathLength(X509Certificate cert, int max) {
    int pl = cert.getBasicConstraints();
    return pl < 0 || pl <= max || pl == Integer.MAX_VALUE;
}

Try / catch

try {
    handler.authenticate(credential);
} catch (FailedLoginException e) {
    // path length exceeds max: raise cas.authn.x509.max-path-length
}

Prevention

When it happens

Trigger: A CA certificate with an explicit pathLenConstraint value greater than cas.authn.x509.max-path-length is presented during X.509 authentication.

Common situations: maxPathLength left at a small default while the real PKI hierarchy has more intermediate CA levels; after an org merge the new chains are deeper than the configured limit.

Understand the failure class

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/2870df6bf6204844. 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:254

                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),
     * keyEncipherment (2), dataEncipherment (3), keyAgreement (4),
     * keyCertSign (5), cRLSign (6), encipherOnly (7), decipherOnly (8) }
     *
     * @param certificate the certificate
     * @return true, if  valid key usage
     */
    private boolean isValidKeyUsage(final X509Certificate certificate) {
        LOGGER.debug("Checking certificate keyUsage extension");
        val keyUsage = certificate.getKeyUsage();
        if (keyUsage == null) {
            LOGGER.warn("Configuration specifies checkKeyUsage but keyUsage extension not found in certificate.");

View on GitHub (pinned to e7288fc434)