apereo/cas · error · AccountNotFoundException
YubiKey id is not recognized in registry
Error message
YubiKey id is not recognized in registry
What it means
YubiKeyAuthenticationHandler.doAuthentication throws AccountNotFoundException when the YubiKey OTP's public ID is not registered for the authenticated user in the configured YubiKey account registry. CAS checks registration before contacting the YubiCloud verification service, so an unregistered device is treated as an unknown account rather than a bad credential. This prevents wasting a verification API call for a device the server never enrolled.
Solutions
- Register the YubiKey public id for the user in the configured registry (cas.authn.yubikey[0].registry.* or the YubiKeyAccountRegistry bean).
- Verify the authenticated principal id matches the key the device is registered under; adjust principal transformation or registry lookup if ids differ.
- If devices should be accepted globally without per-user registration, configure a custom YubiKeyAccountValidator/account registry that always validates.
- Check the registry data store actually contains the record (e.g. inspect the JSON/LDAP entry) and reload/refresh it.
Example fix
// before: no registration -> AccountNotFoundException
// after: register device programmatically
@Bean
public YubiKeyAccountRegistry yubiKeyAccountRegistry() {
return (uid, yubiId) -> List.of("yubiUser").contains(uid) && yubiId.startsWith("vvqlrtb");
} Defensive patterns
Strategy: validation
Validate before calling
// before authenticating, check registration
String publicId = registry.getAccountValidator().getTokenPublicId(otp);
if (!registry.isYubiKeyRegisteredFor(principal.getId(), publicId)) {
// prompt user to register device or block login
} Type guard
boolean isDeviceRegistered(YubiKeyRegistry registry, String uid, String otp) {
var publicId = registry.getAccountValidator().getTokenPublicId(otp);
return publicId != null && registry.isYubiKeyRegisteredFor(uid, publicId);
} Try / catch
try {
authenticate(otp);
} catch (AccountNotFoundException e) {
LOGGER.warn("YubiKey [{}] not registered for user", otp.substring(0, 12));
// show device-registration flow
} Prevention
- Enroll every YubiKey public id for each user before enabling YubiKey MFA for them.
- Keep principal id consistent (disable randomizing ids for the yubikey flow if registry keys by username).
- Audit registry entries periodically against actual users.
When it happens
Trigger: A user submits a YubiKey OTP whose public ID (first ~12 modhex chars) has not been registered via the YubiKey account registry (e.g. cas.authn.yubikey registry settings) for that specific username.
Common situations: User tries to log in with a YubiKey enrolled for a different account; admin never registered the device for the user; registry (JSON/LDAP/etc.) data was wiped or the user field mismatches principal id (case or attribute-mapped id differences).
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Unable to extract credentials for multifactor authentication
- Duo Security authentication has failed
- cannot be found in the registry
- Cannot validate authentication for: [login]
- Radius authentication failed for user
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/8f0a389fd3bcb12b.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-yubikey-core/src/main/java/org/apereo/cas/adaptors/yubikey/YubiKeyAuthenticationHandler.java:91
@Override
protected AuthenticationHandlerExecutionResult doAuthentication(final Credential credential, final Service service) throws GeneralSecurityException {
val yubiKeyCredential = (YubiKeyCredential) credential;
val otp = yubiKeyCredential.getToken();
if (!YubicoClient.isValidOTPFormat(otp)) {
LOGGER.debug("Invalid OTP format [{}]", otp);
throw new AccountNotFoundException("OTP format is invalid");
}
val authentication = Objects.requireNonNull(WebUtils.getInProgressAuthentication(),
"CAS has no reference to an authentication event to locate a principal");
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)