apereo/cas · error

Passwordless account

Error message

Passwordless account [{}] does not have the required attribute [{}] with value pattern [{}]

What it means

LdapPasswordlessUserAccountStore.findUser filters out accounts that lack the LDAP required attribute matching the required value regex; it logs this warning and returns Optional.empty, so CAS behaves as if the passwordless account does not exist.

Solutions

  1. Confirm the user's LDAP entry contains the required attribute value (ldapsearch)
  2. Verify cas.authn.passwordless.accounts.ldap.required-attribute and required-attribute-value settings
  3. Check the LDAP search base/filter actually returns that attribute
  4. Adjust the regex (RegexUtils.find does partial matching) to match real values

Example fix

// before
cas.authn.passwordless.accounts.ldap.required-attribute-value=^pwdless$
// after
cas.authn.passwordless.accounts.ldap.required-attribute-value=passwordless-eligible
Defensive patterns

Strategy: validation

Validate before calling

List<String> vals = ldapEntry.get(requiredAttribute);
boolean ok = vals != null && vals.stream().anyMatch(v -> v != null && Pattern.compile(requiredValuePattern).matcher(v).find());

Try / catch

store.findUser(id).orElseThrow(() -> new AccountNotFoundException(id));

Prevention

When it happens

Trigger: cas.authn.passwordless.accounts.ldap required-attribute and required-attribute-value are set, and none of the user's values for that attribute match the regex during findUser.

Common situations: User not in the required LDAP group; attribute not returned by the LDAP search filter/base DN; regex mismatch due to case or partial-match expectations; typos in attribute name.

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/d28deac1e5a18f8c. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-passwordless-ldap/src/main/java/org/apereo/cas/impl/account/LdapPasswordlessUserAccountStore.java:62

    public Optional<PasswordlessUserAccount> findUser(final PasswordlessAuthenticationRequest request) {
        try {
            val filter = LdapUtils.newLdaptiveSearchFilter(ldapProperties.getSearchFilter(),
                LdapUtils.LDAP_SEARCH_FILTER_DEFAULT_PARAM_NAME,
                CollectionUtils.wrap(request.getUsername()));

            LOGGER.debug("Constructed LDAP filter [{}] to locate passwordless account", filter);
            val response = connectionFactory.executeSearchOperation(ldapProperties.getBaseDn(), filter, ldapProperties.getPageSize());
            LOGGER.debug("LDAP response for passwordless account is [{}]", response);

            if (LdapUtils.containsResultEntry(response)) {
                val passwordlessUserAccount = buildPasswordlessUserAccount(request, response);
                LOGGER.debug("Final passwordless account is [{}]", passwordlessUserAccount);

                if (StringUtils.isNotBlank(ldapProperties.getRequiredAttribute())
                    && StringUtils.isNotBlank(ldapProperties.getRequiredAttributeValue())) {
                    val attributeValues = passwordlessUserAccount.getAttributes().getOrDefault(ldapProperties.getRequiredAttribute(), List.of());
                    if (attributeValues.stream().noneMatch(value -> RegexUtils.find(ldapProperties.getRequiredAttributeValue(), value.toString()))) {
                        LOGGER.warn("Passwordless account [{}] does not have the required attribute [{}] with value pattern [{}]",
                            passwordlessUserAccount, ldapProperties.getRequiredAttribute(), ldapProperties.getRequiredAttributeValue());
                        return Optional.empty();
                    }
                }
                val result = Optional.of(passwordlessUserAccount);
                customizerList
                    .stream()
                    .filter(BeanSupplier::isNotProxy)
                    .forEach(customizer -> customizer.customize(result));
                return result;
            }
        } catch (final Exception e) {
            LoggingUtils.error(LOGGER, e);
        }
        return Optional.empty();
    }

    protected PasswordlessUserAccount buildPasswordlessUserAccount(final PasswordlessAuthenticationRequest request,

View on GitHub (pinned to e7288fc434)