apereo/cas · error · FailedLoginException

throwable.getMessage()

Error message

throwable.getMessage()

What it means

The predefined-accounts JAAS login module wraps any failure of callbackHandler.handle() (which collects the username/password callbacks) into a FailedLoginException whose message is the underlying throwable's message. It fires when the callback handler cannot supply credentials — typically no NameCallback/PasswordCallback handler is wired or the caller aborted. The username/password then cannot be checked against the configured 'accounts' option.

Solutions

  1. Ensure a callback handler able to supply name/password callbacks is configured for this JAAS login module
  2. Check the underlying throwable message for the actual callback failure cause
  3. Verify the 'accounts' JAAS option format is account::password entries separated by commas
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/handler/support/jaas/AccountsPreDefinedLoginModule.java:53 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/handler/support/jaas/AccountsPreDefinedLoginModule.java:53

        val providedAccounts = options.containsKey("accounts") ? options.get("accounts").toString() : null;
        if (StringUtils.isNotBlank(providedAccounts)) {
            val eachAccount = org.springframework.util.StringUtils.commaDelimitedListToSet(providedAccounts);
            eachAccount.stream()
                .map(account -> Splitter.on("::").splitToList(account))
                .filter(results -> results.size() == 2)
                .forEach(results -> accounts.put(results.getFirst(), results.get(1)));
        }
    }

    @Override
    public boolean login() throws LoginException {
        val nameCallback = new NameCallback("username");
        val passwordCallback = new PasswordCallback("password", false);

        FunctionUtils.doAndHandle(_ -> {
            callbackHandler.handle(new Callback[]{nameCallback, passwordCallback});
        }, throwable -> {
            throw new FailedLoginException(throwable.getMessage());
        }).accept(nameCallback);

        val username = nameCallback.getName();
        if (accounts.containsKey(username)) {
            val password = new String(passwordCallback.getPassword());
            this.succeeded = accounts.get(username).equals(password);
            subject.getPrincipals().add(new StaticPrincipal(username));
            return true;
        }
        this.succeeded = false;
        return false;
    }

    @Override
    public boolean commit() {
        return this.succeeded;
    }

View on GitHub (pinned to e7288fc434)