apereo/cas · warning

No registration records could be found for

Error message

No registration records could be found for [{}]

What it means

WebAuthnStartAuthenticationAction checks whether the authenticated principal has any WebAuthn credential registrations via webAuthnCredentialRepository.getRegistrationsByUsername. If none exist it logs this warning and returns the error event, blocking WebAuthn MFA because a user with no registered authenticator cannot perform WebAuthn authentication.

Solutions

  1. Have the user complete WebAuthn device registration first (trigger the registration flow) before authentication.
  2. Set cas.authn.mfa.webauthn.core.enabled or the MFA trigger policy so unregistered users are routed to registration instead of hard-failing (e.g. use a WebAuthn MFA trigger that accounts for registration state).
  3. Verify the repository backend holds registrations for that exact username (check casing and attribute resolution).
  4. Confirm the configured webAuthnCredentialRepository points at the same store used during registration.

Example fix

// before: WebAuthn required for everyone, unregistered users fail
// after: allow fallback / route unregistered users to registration
weathermap: configure cas.authn.mfa.webauthn.core.location-policy / trigger groovy to check registrations before forcing webauthn
Defensive patterns

Strategy: validation

Validate before calling

boolean registered = !webAuthnCredentialRepository.getRegistrationsByUsername(principal.getId()).isEmpty();
if (!registered) {
    routeToWebAuthnRegistration();
}

Prevention

When it happens

Trigger: A user forced into WebAuthn MFA (required authentication method or per-service policy) who has never completed device registration; the repository (account store/registry) lookup returns an empty registration list for the principal id.

Common situations: New users onboarded with WebAuthn MFA set to required before registering a device; user renamed so the username no longer matches registration records; WebAuthn registration storage wiped or pointing at a different backend; registration records stored under a different principal id casing.

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


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

Appendix: source

Thrown at support/cas-server-support-webauthn-core-webflow/src/main/java/org/apereo/cas/webauthn/web/flow/WebAuthnStartAuthenticationAction.java:50

 */
@RequiredArgsConstructor
@Getter
@Slf4j
public class WebAuthnStartAuthenticationAction extends AbstractMultifactorAuthenticationAction<WebAuthnMultifactorAuthenticationProvider> {
    protected final CasConfigurationProperties casProperties;
    protected final TicketRegistry ticketRegistry;
    protected final TicketFactory ticketFactory;
    protected final RegistrationStorage webAuthnCredentialRepository;
    protected final TenantExtractor tenantExtractor;
    
    @Override
    protected @Nullable Event doExecuteInternal(final RequestContext requestContext) throws Throwable {
        val authentication = WebUtils.getAuthentication(requestContext);
        val principal = resolvePrincipal(authentication.getPrincipal(), requestContext);
        LOGGER.trace("Checking registration record for [{}]", principal.getId());
        val registrations = webAuthnCredentialRepository.getRegistrationsByUsername(principal.getId());
        if (registrations.isEmpty()) {
            LOGGER.warn("No registration records could be found for [{}]", principal.getId());
            return error();
        }

        if (casProperties.getAuthn().getMfa().getWebAuthn().getCore().isQrCodeAuthenticationEnabled()) {
            val transientFactory = (TransientSessionTicketFactory) ticketFactory.get(TransientSessionTicket.class);
            val ticket = transientFactory.create(Map.of(Principal.class.getName(), principal));
            val storedTicket = ticketRegistry.addTicket(ticket);
            val urlBuilder = new URIBuilder(casProperties.getServer().getPrefix());
            urlBuilder.appendPath(BaseWebAuthnController.BASE_ENDPOINT_WEBAUTHN);
            urlBuilder.appendPath(WebAuthnQRCodeController.ENDPOINT_QR_VERIFY);
            requestContext.getFlowScope().put("QRCodeUri", urlBuilder.toString());
            urlBuilder.appendPath(storedTicket.getId());
            val qrCodeBase64 = QRUtils.generateQRCode(urlBuilder.toString(), QRUtils.SIZE, QRUtils.SIZE);
            requestContext.getFlowScope().put("QRCode", qrCodeBase64);
            requestContext.getFlowScope().put("QRCodeTicket", storedTicket);
            WebUtils.putPrincipal(requestContext, principal);
        }

View on GitHub (pinned to e7288fc434)