apereo/cas · error · UnauthorizedServiceException
Denied
Error message
Denied: %s
What it means
Delegated client lookup failed: findDelegatedClientByName in DelegatedClientAuthenticationAction cannot resolve the requested identity-provider client name against the pac4j IdentityProviders configuration, so CAS denies access with an UnauthorizedServiceException. This guards against requests naming an unconfigured or unauthorized provider.
Solutions
- Verify the clientName parameter matches a pac4j client registered in cas.authn.pac4j.* configuration
- Check that no service-level filter (unauthorized redirection policy / custom Authorizer) is excluding the client
- Confirm the DelegatedClientIdentityProviderConfigurationFactory includes the client for the requested service
- Enable debug logging for org.apereo.cas.support.pac4j.web.flow to see why the client set is empty
Example fix
// before cas.authn.pac4j.oidc[0].client-name = GitHUB // after (matches the name used in the request) cas.authn.pac4j.oidc[0].client-name = GitHubClient
Defensive patterns
Strategy: validation
Validate before calling
if (cas.getIdentityProviders().findClient(clientName, webContext).isEmpty()) {
// route to an error event instead of invoking the action
} Try / catch
try { ... } catch (UnauthorizedServiceException e) { return errorEvent("delegationDenied", e); } Prevention
- Keep delegated client names centralized/shared constants
- Verify client availability in integration tests
- Monitor the warn log 'Delegated client ... can not be located'
When it happens
Trigger: A request parameter (e.g. client_name) names a delegated client that is not registered in the DelegatedClientIdentityProviderConfigurationFactory results, is filtered out as unauthorized for the service, or findClient returns empty for the given JEEContext.
Common situations: Typo in the client name in links or service config; client disabled by an AuthorizationGenerator/service filter; config change after CAS restart removed the provider; user bookmarked an old SSO link.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Authentication request was denied from the provider
- Delegated authentication has failed with client
- No state could be found to determine session state
- Client name for [ ] is set to a generated value of [ ]…
- Authentication cannot find attribute
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/324e9dd1c2228f6a.
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:266
protected Optional<ClientCredential> populateContextWithClientCredential(final BaseClient client,
final RequestContext requestContext) {
return configContext.getCredentialExtractors()
.stream()
.filter(BeanSupplier::isNotProxy)
.map(extractor -> extractor.extract(client, requestContext))
.flatMap(Optional::stream)
.findFirst();
}
protected BaseClient findDelegatedClientByName(final String clientName, final RequestContext context) {
val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(context);
val response = WebUtils.getHttpServletResponseFromExternalWebflowContext(context);
val webContext = new JEEContext(request, response);
val clientResult = configContext.getIdentityProviders().findClient(clientName, webContext);
if (clientResult.isEmpty()) {
LOGGER.warn("Delegated client [{}] can not be located", clientName);
throw UnauthorizedServiceException.denied("Denied: %s".formatted(clientName));
}
val client = (BaseClient) clientResult.get();
client.init();
return client;
}
private void verifyClientIsAuthorizedForService(final RequestContext requestContext, @Nullable final Service service, final BaseClient client) {
LOGGER.debug("Delegated authentication client is [{}] with service [{}]", client, service);
if (service != null) {
val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
request.setAttribute(CasProtocolConstants.PARAMETER_SERVICE, service);
}
if (!isDelegatedClientAuthorizedForService(client, service, requestContext)) {
LOGGER.error("Delegated client [{}] is not authorized by service [{}]", client, service);
throw UnauthorizedServiceException.denied("Denied: %s".formatted(service));
}
}
View on GitHub (pinned to e7288fc434)