apereo/cas · error · FailedLoginException

YubiKey validation failed:

Error message

YubiKey validation failed: 

What it means

The catch-all Throwable handler in doAuthentication logs the original error and rethrows FailedLoginException("YubiKey validation failed: " + cause.getMessage()). It wraps any exception during the YubiCloud verification call (network failure, client construction error, runtime exceptions) into a generic login failure.

Solutions

  1. Read the wrapped cause message in the log (LoggingUtils.error prints the full stack) to find the root failure.
  2. Test outbound HTTPS connectivity from the CAS host to api.yubikey.com; configure proxy if needed.
  3. Correct cas.authn.yubikey[0].client-id / secret-key credentials.
  4. If YubiCloud is down or unreachable, switch cas.authn.yubikey[0].api-server to an on-prem ykval validation server URL.

Example fix

// before: firewalled host fails verification
// after: route via internal validation server
cas.authn.yubikey[0].api-server=https://ykval.internal.example.com/wsapi/2.0/verify
// and/or set JVM proxy flags: -Dhttps.proxyHost=proxy -Dhttps.proxyPort=3128
Defensive patterns

Strategy: retry

Validate before calling

// reachability probe before login flow
new URL(cas.authn.yubikey.apiServer or "https://api.yubikey.com/wsapi/2.0/verify")
    .openConnection().connect(); // IOException means network issue

Try / catch

try {
    handler.authenticate(credential);
} catch (FailedLoginException e) {
    if (e.getMessage().startsWith("YubiKey validation failed")) {
        // transient network issue: back off and retry
    }
}

Prevention

When it happens

Trigger: client.verify(otp) throws: network unreachable/DNS failure to YubiCloud, invalid API credentials causing client errors, timeouts, or any runtime exception inside the verify path.

Common situations: CAS server has no outbound internet access or a proxy is required; wrong client id/secret; YubiCloud outage; firewall blocks api.yubikey.com (port 443).

Related errors


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

Appendix: source

Thrown at support/cas-server-support-yubikey-core/src/main/java/org/apereo/cas/adaptors/yubikey/YubiKeyAuthenticationHandler.java:104

        val principal = authentication.getPrincipal();
        val uid = principal.getId();
        val publicId = registry.getAccountValidator().getTokenPublicId(otp);
        if (!this.registry.isYubiKeyRegisteredFor(uid, publicId)) {
            LOGGER.debug("YubiKey public id [{}] is not registered for user [{}]", publicId, uid);
            throw new AccountNotFoundException("YubiKey id is not recognized in registry");
        }

        try {
            val response = this.client.verify(otp);
            val status = response.getStatus();
            if (status.compareTo(ResponseStatus.OK) == 0) {
                LOGGER.debug("YubiKey response status [{}] at [{}]", status, response.getTimestamp());
                return createHandlerResult(yubiKeyCredential, this.principalFactory.createPrincipal(uid));
            }
            throw new FailedLoginException("Authentication failed with status: " + status);
        } catch (final Throwable e) {
            LoggingUtils.error(LOGGER, e);
            throw new FailedLoginException("YubiKey validation failed: " + e.getMessage());
        }
    }
}

View on GitHub (pinned to e7288fc434)