apereo/cas · warning

Configuration specifies checkKeyUsage but keyUsage…

Error message

Configuration specifies checkKeyUsage but keyUsage extension not found in certificate.

What it means

The handler is configured to check the keyUsage extension (checkKeyUsage=true) but the presented certificate contains no keyUsage extension at all. isValidKeyUsage logs this warning and returns !requireKeyUsage, meaning the certificate is rejected only when keyUsage is also marked as required; otherwise validation continues despite the missing extension.

Solutions

  1. If your certificates intentionally lack keyUsage, either disable the check (set check-key-usage=false) or keep require-key-usage=false so missing extensions are tolerated.
  2. Re-issue the client certificate with a template/profile that includes the keyUsage extension (best long-term fix).
  3. If the extension must exist and be valid, leave require-key-usage=true and have your CA issue certificates with keyUsage; certificates without it will be rejected as expected.
  4. Inspect the failing certificate (openssl x509 -text) to confirm keyUsage is truly absent before changing configuration.

Example fix

// before
cas.authn.x509.check-key-usage=true
cas.authn.x509.require-key-usage=true
// after (certificates without keyUsage are accepted)
cas.authn.x509.check-key-usage=true
cas.authn.x509.require-key-usage=false
Defensive patterns

Strategy: validation

Validate before calling

// Check the certificate before validation:
val keyUsage = certificate.getKeyUsage();
if (keyUsage == null && requireKeyUsage) {
    logger.warn("Certificate {} lacks keyUsage but it is required; will be rejected", certificate.getSerialNumber());
}

Try / catch

try {
    handler.authenticate(x509Credential);
} catch (FailedLoginException e) {
    if (certificate.getKeyUsage() == null) {
        logger.warn("Certificate has no keyUsage extension; relax require-key-usage or reissue cert");
    }
    throw e;
}

Prevention

When it happens

Trigger: validate() calls isValidKeyUsage() during certificate validation; certificate.getKeyUsage() returns null because the certificate was issued without a keyUsage extension while cas.authn.x509 check-key-usage is enabled in configuration.

Common situations: CA issues certificates without the keyUsage extension (common with some client/certificate templates); operator enables checkKeyUsage based on documentation without knowing their CA's certificate profiles; migration between CAs with different certificate templates.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

                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.");
            return !this.requireKeyUsage;
        }

        val func = FunctionUtils.doIf(c -> isCritical(certificate, KEY_USAGE_OID) || requireKeyUsage,
            t -> {
                LOGGER.debug("KeyUsage extension is marked critical or required by configuration.");
                return keyUsage[0];
            },
            f -> {
                LOGGER.debug("KeyUsage digitalSignature=%s, Returning true since keyUsage validation not required by configuration.");
                return Boolean.TRUE;
            });
        return func.apply(certificate);
    }

    /**
     * Checks if is certificate allowed based no the pattern given.
     *

View on GitHub (pinned to e7288fc434)