apereo/cas · error · UnauthorizedServiceException

Authentication request was denied from the provider

Error message

Authentication request was denied from the provider %s

What it means

When resolving the delegated identity provider in DelegatedClientAuthenticationStoreWebflowStateAction, the provider lookup or authorization call throws; CAS converts that throwable into an UnauthorizedServiceException stating the authentication request was denied from the provider. It signals the provider exists in config but rejected/refused this authentication attempt.

Solutions

  1. Check the delegated client's authorized services/attribute rules in cas.authn.pac4j.* for the calling service
  2. Inspect the wrapped throwable (logged as a warning by LoggingUtils) for the root cause
  3. Verify the service definition allows delegated authentication for this provider
  4. Test the provider independently (valid clientId/secret, reachable discovery endpoint)

Example fix

// before
@JsonSerialize... // service filter excludes provider
"clientId": "abc", "allowedProviders": ["Cas"]
// after
"allowedProviders": ["Cas", "SAML2-IdP"],
Defensive patterns

Strategy: try-catch

Try / catch

try { storeState(...) } catch (UnauthorizedServiceException e) { renderDelegationDeniedPage(e); }

Prevention

When it happens

Trigger: isDelegatedClientAuthorizedForService (or a downstream pac4j call) throws while processing provider clientName during webflow state storage; the exception path via FunctionUtils.wrap wraps the throwable.

Common situations: Client not authorized for the requested service (regex/attribute filter mismatch); provider redirect failed mid-flow; user denied consent at the IdP and the error propagated back.

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/526f7a93aa5670bf. Report an issue: GitHub.

Appendix: source

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

                    .findFirst()
                    .map(IndirectClient.class::cast)
                    .stream()
                    .peek(InitializableObject::init)
                    .findFirst()
                    .map(Unchecked.function(client -> {
                        val ticket = delegatedClientAuthenticationWebflowManager.store(requestContext, webContext, client);
                        requestContext.getFlowScope().put(TransientSessionTicket.class.getName(), ticket);
                        return ticket;
                    }))
                    .map(ticket -> eventFactory.event(this,
                        CasWebflowConstants.TRANSITION_ID_REDIRECT, ticket.getClass().getName(), ticket))
                    .stream()
                    .findFirst()
                    .orElseThrow(() -> UnauthorizedServiceException.denied("Unable to locate client identity provider %s".formatted(clientName))),
                throwable -> {
                    val message = String.format("Authentication request was denied from the provider %s", clientName);
                    LoggingUtils.warn(LOGGER, message, throwable);
                    throw UnauthorizedServiceException.wrap(throwable);
                })
            .get();
    }

    protected boolean isDelegatedClientAuthorizedForService(final Client client,
                                                            @Nullable final Service service,
                                                            final RequestContext requestContext) {
        return configContext.getDelegatedClientIdentityProviderAuthorizers()
            .stream()
            .allMatch(Unchecked.predicate(authz -> authz.isDelegatedClientAuthorizedForService(client, service, requestContext)));
    }

}

View on GitHub (pinned to e7288fc434)