@Override
    protected AuthenticationHandlerExecutionResult doAuthentication(final Credential credential, final Service service) throws Throwable {
        val x509Credential = (X509CertificateCredential) credential;
        val certificates = x509Credential.getCertificates();

        var clientCert = (X509Certificate) null;
        var hasTrustedIssuer = false;
        for (var i = certificates.length - 1; i >= 0; i--) {
            val certificate = certificates[i];
            LOGGER.debug("Evaluating [{}]", CertUtils.toString(certificate));

            validate(certificate);

            if (!hasTrustedIssuer) {
                hasTrustedIssuer = isCertificateFromTrustedIssuer(certificate);
            }

            val pathLength = certificate.getBasicConstraints();
            if (pathLength < 0) {
                LOGGER.debug("Found valid client certificate");
                clientCert = certificate;
            } else {
                LOGGER.debug("Found valid CA certificate");
            }
        }
        if (hasTrustedIssuer && clientCert != null) {
            x509Credential.setCertificate(clientCert);
            return new DefaultAuthenticationHandlerExecutionResult(this, x509Credential,
                this.principalFactory.createPrincipal(x509Credential.getId()));
        }
        LOGGER.warn("Either client certificate could not be determined, or a trusted issuer could not be located");
        throw new FailedLoginException();
    }
Note: The call to getBasicConstraints returns pathLenConstraints which is generally greater than or equal to zero
when this is a CA cert and -1 when it's not.

@param credential Credential to authenticate.
@param service the requesting service.
@return Authn handler execution result.
@throws GeneralSecurityException security exception
support/cas-server-support-x509-core/src/main/java/org/apereo/cas/adaptors/x509/authentication/handler/support/X509CredentialsAuthenticationHandler.java