apereo/cas · warning

[ ] Caused by: [ ]

Error message

[{}] Caused by: [{}]

What it means

RestResourceUtils.createResponseEntityForAuthnFailure converts a failed REST authentication attempt into a 401 UNAUTHORIZED response whose body lists authentication_exceptions and their cause messages. This warning logs the top-level exception plus its mapped causes. The error indicates the credentials supplied to the REST endpoint (e.g. /v1/tickets or REST protocol) failed authentication.

Solutions

  1. Verify the client is sending correct, current credentials (correct Basic Auth base64 encoding or properly form-encoded username/password).
  2. Check the logged authnExceptions list in this warning to see the underlying handler failure (bad password vs. account locked vs. backend unreachable).
  3. Confirm the relevant authentication handler is configured and reachable for REST authentication requests.
  4. Fix or rotate the service account credentials on the client side; expect HTTP 401 until credentials validate.

Example fix

// before: malformed client call
curl -u 'user:wrongpass' https://cas.example.org/cas/v1/tickets -d 'service=...'

// after: correct credentials
curl -u 'user:correctpass' https://cas.example.org/cas/v1/tickets -d 'service=...'
Defensive patterns

Strategy: try-catch

Validate before calling

if (credentials == null || !StringUtils.hasText(credentials.getUsername()) || !StringUtils.hasText(credentials.getPassword())) {
    throw new BadCredentialsException("Username and password are required");
}

Try / catch

try {
    ResponseEntity<String> resp = restTemplate.postForEntity(casTicketsUrl, request, String.class);
} catch (HttpStatusCodeException e) {
    if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
        // 401 body contains authentication_exceptions; rotate credentials and retry once
    }
}

Prevention

When it happens

Trigger: POST to a CAS REST endpoint with Basic Auth or credentials body whose username/password do not validate against any configured authentication handler; credential extraction produced exceptions mapped into authnExceptions.

Common situations: Clients sending wrong/expired passwords to the REST ticket endpoint; service integrations using old service accounts; REST authentication handler misconfigured or backend (LDAP/JDBC) unreachable so authentication fails; encoding issues in the Authorization header.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-rest-core/src/main/java/org/apereo/cas/support/rest/resources/RestResourceUtils.java:54

     * @param e                  the e
     * @param request            the http request
     * @param applicationContext the application context
     * @return the response entity
     */
    public static ResponseEntity<String> createResponseEntityForAuthnFailure(final AuthenticationException e,
                                                                             final HttpServletRequest request,
                                                                             final ApplicationContext applicationContext) {
        try {
            val authnExceptions = e.getHandlerErrors().values()
                .stream()
                .map(ex -> mapExceptionToMessage(e, request, applicationContext, ex))
                .collect(Collectors.toList());
            if (authnExceptions.isEmpty()) {
                authnExceptions.add(mapExceptionToMessage(e, request, applicationContext, e));
            }
            val errorsMap = new HashMap<String, List<String>>(1);
            errorsMap.put("authentication_exceptions", authnExceptions);
            LOGGER.warn("[{}] Caused by: [{}]", e.getMessage(), authnExceptions);

            return new ResponseEntity<>(MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(errorsMap), HttpStatus.UNAUTHORIZED);
        } catch (final JacksonException exception) {
            LoggingUtils.error(LOGGER, e);
            return new ResponseEntity<>(StringEscapeUtils.escapeHtml4(e.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private static String mapExceptionToMessage(final AuthenticationException authnhandlerErrors,
                                                final HttpServletRequest request,
                                                final ApplicationContext applicationContext,
                                                final Throwable ex) {
        val authnMsg = StringUtils.defaultIfBlank(StringEscapeUtils.escapeHtml4(ex.getMessage()),
            "Authentication Failure: " + authnhandlerErrors.getMessage());
        val authnBundleMsg = getTranslatedMessageForExceptionClass(ex.getClass().getSimpleName(), request, applicationContext);
        return String.format("%s:%s", authnMsg, authnBundleMsg);
    }

View on GitHub (pinned to e7288fc434)