apereo/cas · error · FailedLoginException

sent an unacceptable response status code

Error message

<callbackUrl> sent an unacceptable response status code

What it means

A proxy-authentication attempt failed because the HttpBasedServiceCredential's callback URL did not pass the HTTP reachability check: httpClient.isValidEndPoint() returned false, meaning the callback endpoint responded with an unacceptable/non-2xx status or was unreachable. This is the generic guard for the pgtUrl/proxy-callback validation step of the CAS proxy protocol; the input at fault is the service's callback URL.

Solutions

  1. Verify the callback URL is reachable from the CAS server and returns HTTP 200
  2. Check the service's proxy policy configuration to ensure the callback URL is allowed
  3. Inspect the callback endpoint for outages, TLS issues, or redirects that HttpClient rejects
  4. Confirm network/firewall rules allow the CAS server to reach the callback host
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/ProxyAuthenticationHandler.java:51 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/2ff0447c9af14925. Report an issue: GitHub.

Appendix: source

Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/handler/support/ProxyAuthenticationHandler.java:51

                                      final Integer order, final HttpClient httpClient) {
        super(name, principalFactory, order);
        this.httpClient = httpClient;
    }

    @Override
    public AuthenticationHandlerExecutionResult authenticate(final Credential credential, final Service service) throws Throwable {
        val httpCredential = (HttpBasedServiceCredential) credential;
        if (!httpCredential.getService().getProxyPolicy()
            .isAllowedProxyCallbackUrl(httpCredential.getService(), httpCredential.getCallbackUrl())) {
            LOGGER.warn("Proxy policy for service [{}] cannot authorize the requested callback url [{}].",
                httpCredential.getService(), httpCredential.getCallbackUrl());
            throw new FailedLoginException(httpCredential.getCallbackUrl() + " cannot be authorized");
        }

        LOGGER.debug("Attempting to authenticate [{}]", httpCredential);
        val callbackUrl = httpCredential.getCallbackUrl();
        if (!httpClient.isValidEndPoint(callbackUrl)) {
            throw new FailedLoginException(callbackUrl.toExternalForm() + " sent an unacceptable response status code");
        }
        val principalId = httpCredential.getCredentialMetadata().getId();
        val proxyPrincipal = principalFactory.createPrincipal(principalId);
        return new DefaultAuthenticationHandlerExecutionResult(this, httpCredential, proxyPrincipal);
    }

    @Override
    public boolean supports(final Credential credential) {
        return credential instanceof HttpBasedServiceCredential;
    }

    @Override
    public boolean supports(final Class<? extends Credential> clazz) {
        return HttpBasedServiceCredential.class.isAssignableFrom(clazz);
    }
}

View on GitHub (pinned to e7288fc434)