apereo/cas · error · UnauthorizedServiceException

ServiceManagement: Unauthorized Service Access. Service

Error message

ServiceManagement: Unauthorized Service Access. Service [%s] is not enabled in the CAS service registry.

What it means

The service is registered but its access strategy says service access is not allowed (entry disabled, expired, or otherwise restricted), so verifyRegisteredServiceProperties throws UnauthorizedServiceException.denied with this message. This is an explicit policy denial, not a missing record.

Solutions

  1. Open the service in the management console (or its JSON entry) and set enabled=true, or fix the access strategy constraints.
  2. Check validFrom/validUntil dates on the registry entry and extend or correct them.
  3. Review the entry's access strategy (e.g. DefaultRegisteredServiceAccessStrategy, unauthorized redirect settings) for conditions that deny this particular service/principal.

Example fix

// before
{
  "serviceId": "^https://myapp\.example\.org/.*",
  "id": 10000001,
  "accessStrategy": { "@class": "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy", "enabled": false }
}

// after
{
  "serviceId": "^https://myapp\.example\.org/.*",
  "id": 10000001,
  "accessStrategy": { "@class": "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy", "enabled": true }
}
Defensive patterns

Strategy: validation

Validate before calling

// before validating tickets, check the registry entry's access strategy
RegisteredService rs = servicesManager.findServiceBy(service);
if (rs == null || !rs.getAccessStrategy().isServiceAccessAllowed(rs, service)) {
    throw new IllegalStateException("Service disabled or expired in CAS registry: " + service.getId());
}

Try / catch

try {
    // validate ticket
} catch (UnauthorizedServiceException e) {
    if (e.getMessage().contains("not enabled")) { /* re-enable service or fix validFrom/validUntil */ }
}

Prevention

When it happens

Trigger: verifyRegisteredServiceProperties (called from getServiceCredentialsFromRequest during ticket validation) calls registeredService.getAccessStrategy().isServiceAccessAllowed(registeredService, service) and it returns false for the matched registered service.

Common situations: Service registry entry toggled to disabled (enabled=false); entry's validFrom/validUntil date window expired; authorized to proxy / allowed attribute policies blocking access after a registry edit or bulk import.

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

Appendix: source

Thrown at support/cas-server-support-validation-core/src/main/java/org/apereo/cas/web/AbstractServiceValidateController.java:70

 * @author Misagh Moayyed
 * @since 3.0.0
 */
@Slf4j
@Getter
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class AbstractServiceValidateController extends AbstractDelegateController {
    private final ServiceValidateConfigurationContext serviceValidateConfigurationContext;

    private static void verifyRegisteredServiceProperties(final RegisteredService registeredService, final Service 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("ServiceManagement: Unauthorized Service Access. "
                + "Service [%s] is not enabled in the CAS service registry.", service.getId());
            LOGGER.warn(msg);
            throw UnauthorizedServiceException.denied(msg);
        }
    }

    protected Ticket handleProxyGrantingTicketDelivery(final String serviceTicketId, final Credential credential) throws Throwable {
        val serviceTicket = serviceValidateConfigurationContext.getTicketRegistry().getTicket(serviceTicketId, ServiceTicket.class);
        val authenticationResult = serviceValidateConfigurationContext.getAuthenticationSystemSupport()
            .finalizeAuthenticationTransaction(serviceTicket.getService(), credential);
        val proxyGrantingTicket = serviceValidateConfigurationContext.getCentralAuthenticationService()
            .createProxyGrantingTicket(serviceTicketId, authenticationResult);
        LOGGER.debug("Generated proxy-granting ticket [{}] off of service ticket [{}] and credential [{}]",
            proxyGrantingTicket.getId(), serviceTicketId, credential);
        return proxyGrantingTicket;
    }

    @Override
    public ModelAndView handleRequestInternal(final HttpServletRequest request,
                                              final HttpServletResponse response) throws Exception {

View on GitHub (pinned to e7288fc434)