apereo/cas · error · UnauthorizedServiceException

Service Management: Unauthorized Service Access. Service

Error message

Service Management: Unauthorized Service Access. Service [%s] is not allowed access via the service registry.

What it means

The service IS registered, but its RegisteredServiceAccessStrategy.isServiceAccessAllowed() returned false, so the action throws UnauthorizedServiceException.denied with the 'Service Management: Unauthorized Service Access...' message and puts the access strategy's unauthorizedRedirectUrl into flow scope for redirection.

Solutions

  1. Re-enable the service / fix its accessStrategy (set serviceAccessAllowed=true) in the registry
  2. Check and widen the access strategy's startDate/endDate window
  3. Update requiredAttributes/allowedAttributes so the current principal satisfies the policy
  4. Set an unauthorizedRedirectUrl on the access strategy so end users get a friendly redirect instead of a raw error

Example fix

// before
"accessStrategy": {
  "@class": "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy",
  "enabled": false
}
// after
"accessStrategy": {
  "@class": "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy",
  "enabled": true,
  "unauthorizedRedirectUrl": "https://app.example.org/access-denied"
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Precheck access strategy before entering the flow
RegisteredService rs = servicesManager.findServiceBy(service);
if (rs != null && !rs.getAccessStrategy().isServiceAccessAllowed(rs, service)) {
    logger.warn("Access denied by policy for {}", rs.getId());
}

Try / catch

try {
    flow.exec(authorizationCheck);
} catch (UnauthorizedServiceException e) {
    // redirect using unauthorizedRedirectUrl from flow scope
    response.sendRedirect(unauthorizedRedirectUrl);
}

Prevention

When it happens

Trigger: doExecuteInternal calls isServiceAccessAllowed on the resolved registered service and it returns false due to: service disabled, expired (start/end dates), attribute-based release rules failing for the user, or delegated-auth exclusive policy restrictions.

Common situations: Admin disabled the service in the service manager; evaluationOrder/date windows lapsed; required-attributes policy rejects the authenticated principal; user not in an allowed group; scheduled service expiration passed unnoticed.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-actions-core/src/main/java/org/apereo/cas/web/flow/BaseServiceAuthorizationCheckAction.java:47

    private final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies;

    @Override
    protected @Nullable Event doExecuteInternal(final RequestContext context) {
        val serviceInContext = WebUtils.getService(context);
        val service = FunctionUtils.doUnchecked(() -> authenticationRequestServiceSelectionStrategies.resolveService(serviceInContext));
        if (service == null) {
            return success();
        }
        val registeredService = servicesManager.findServiceBy(service);
        if (registeredService == null) {
            val msg = String.format("Service [%s] is not found in service registry.", service.getId());
            LOGGER.warn(msg);
            throw UnauthorizedServiceException.denied(msg);
        }
        if (!registeredService.getAccessStrategy().isServiceAccessAllowed(registeredService, service)) {
            val msg = String.format("Service Management: Unauthorized Service Access. "
                + "Service [%s] is not allowed access via the service registry.", service.getId());
            LOGGER.warn(msg);
            WebUtils.putUnauthorizedRedirectUrlIntoFlowScope(context,
                registeredService.getAccessStrategy().getUnauthorizedRedirectUrl());
            throw UnauthorizedServiceException.denied(msg);
        }
        val delegatedPolicy = registeredService.getAccessStrategy().getDelegatedAuthenticationPolicy();
        WebUtils.putCasLoginFormViewable(context, delegatedPolicy == null || !delegatedPolicy.isExclusive());
        return success();
    }
}

View on GitHub (pinned to e7288fc434)