apereo/cas · error · IllegalArgumentException

Delegated authentication has failed with client

Error message

Delegated authentication has failed with client 

What it means

DelegatedClientAuthenticationAction.doExecuteInternal evaluates the callback response status with a failureEvaluator; when the evaluator detects a failure, it throws IllegalArgumentException("Delegated authentication has failed with client " + clientName), aborting the webflow.

Solutions

  1. Inspect the callback request/IdP error (logs show clientName and status) to learn why the IdP reported failure
  2. Fix the delegated client configuration (secrets, redirect URI) or the user action (cancel/consent denial) accordingly
  3. Check IdP health/status page if the status indicates a server-side 5xx

Example fix

// before
cas.authn.pac4j.oidc[0].generic.secret=stale-secret   // IdP responds 401 on token exchange
// after
cas.authn.pac4j.oidc[0].secret=${OIDC_CLIENT_SECRET}  // rotated, correct secret
Defensive patterns

Strategy: try-catch

Validate before calling

// inspect callback before executing flow
if (request.getParameter("error") != null) { handleDelegationError(request.getParameter("error")); }

Try / catch

try { executeDelegatedFlow(context); }
catch (IllegalArgumentException e) { log clientName; route user to a friendly delegation-failure view; }

Prevention

When it happens

Trigger: The delegated IdP callback returns an HTTP status the failure evaluator classifies as failed (e.g. 401/403/500, OAuth error=access_denied in the callback), while a clientName is present and it is not a logout request.

Common situations: User cancels consent at the IdP (access_denied); wrong client secret causing IdP error responses; IdP downtime returning 5xx; misconfigured redirect/callback URIs producing error redirects.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-pac4j-webflow/src/main/java/org/apereo/cas/web/flow/actions/DelegatedClientAuthenticationAction.java:113

                && ssoEvaluator.singleSignOnSessionExists(context);
            if (isSingleSignOnSessionActive) {
                LOGGER.trace("Found an existing single sign-on session");
                service = populateContextWithService(context, service);
                if (ssoEvaluator.singleSignOnSessionAuthorizedForService(context)) {
                    val providers = configContext.getDelegatedClientIdentityProvidersProducer().produce(context);
                    LOGGER.debug("Skipping delegation and routing back to CAS authentication flow with providers [{}]", providers);
                    return super.doExecuteInternal(context);
                }
                val resolvedService = ssoEvaluator.resolveServiceFromRequestContext(context);
                LOGGER.debug("Single sign-on session is unauthorized for service [{}]", resolvedService);
                removeTicketGrantingTicketIfAny(context, clientName, resolvedService);
            } else if (StringUtils.isNotBlank(clientName) && !isLogoutRequest(clientCredential)) {
                LOGGER.debug("Single sign-on session is inactive for service [{}]", service);
                removeTicketGrantingTicketIfAny(context, clientName, service);
            }

            if (failureEvaluator.evaluate(request, response.getStatus()).isPresent()) {
                throw new IllegalArgumentException("Delegated authentication has failed with client " + clientName);
            }

            if (DelegationWebflowUtils.hasDelegatedClientAuthenticationCandidateProfile(context)) {
                val profile = DelegationWebflowUtils.getDelegatedClientAuthenticationCandidateProfile(context, DelegatedAuthenticationCandidateProfile.class);
                val up = profile.toUserProfile(clientName);
                val clientCredentialSelected = new ClientCredential(clientName, up);
                WebUtils.putCredential(context, clientCredentialSelected);
                return super.doExecuteInternal(context);
            }

            if (clientCredential.isPresent()) {
                service = populateContextWithService(context, service);
                val client = findDelegatedClientByName(clientName, context);
                verifyClientIsAuthorizedForService(context, service, client);
                DelegationWebflowUtils.putDelegatedAuthenticationClientName(context, client.getName());
                if (isLogoutRequest) {
                    val callContext = new CallContext(webContext, configContext.getSessionStore());
                    throw client.processLogout(callContext, clientCredential.get().getCredentials());

View on GitHub (pinned to e7288fc434)