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
- Inspect the callback request/IdP error (logs show clientName and status) to learn why the IdP reported failure
- Fix the delegated client configuration (secrets, redirect URI) or the user action (cancel/consent denial) accordingly
- 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
- Handle IdP error codes (access_denied) as graceful UX, not hard failures
- Keep IdP client secrets/redirect URIs in sync
- Monitor IdP status endpoints
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Client name for [ ] is set to a generated value of [ ]…
- Authentication cannot find attribute
- No custom principal attribute was provided by the client
- CAS cannot use [ ] as the principal attribute id, since the…
- Service access for [ ] is denied
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)