apereo/cas · error

[ ] is not found in the registry or service access is…

Error message

[{}] is not found in the registry or service access is denied.

What it means

CAS's SAML IdP could not locate the requesting SP entityID in the service registry, or the service's access strategy explicitly denied access for the incoming request. verifySamlRegisteredService resolves the entityID as a SamlRegisteredService via ServicesManager.findServiceBy and checks isServiceAccessAllowed; on failure it throws UnauthorizedServiceException.denied. This is a deliberate rejection of an unregistered or disallowed service provider.

Solutions

  1. Verify a SamlRegisteredService exists whose serviceId regex matches the incoming entityID exactly (check case and trailing slashes) in the configured service registry.
  2. Check the service's accessStrategy in the service definition JSON: ensure it is not disabled, expired, and that unauthorized/url policies do not reject the request.
  3. Confirm the service registry source (JSON files, JDBC, etc.) is correctly configured and the service was actually loaded — inspect /cas actuator services endpoint or registry logs.
  4. Enable DEBUG logging for org.apereo.cas.support.saml to see the constructed service object and why findServiceBy returned nothing.

Example fix

// before: entityID 'https://sp.example.com/shib' but service definition pattern only matches https://sp.example.com
{
  "@class": "org.apereo.cas.support.saml.services.SamlRegisteredService",
  "serviceId": "https://sp\.example\.com",
  ...
}
// after: widen/fix the pattern to match the SP's actual entityID
{
  "@class": "org.apereo.cas.support.saml.services.SamlRegisteredService",
  "serviceId": "https://sp\.example\.com/shib",
  ...
}
Defensive patterns

Strategy: validation

Validate before calling

// Admin-side pre-check against the CAS registry
val service = servicesManager.findServiceBy(entityId, SamlRegisteredService.class);
if (service == null || !service.getAccessStrategy().isServiceAccessAllowed(service, webAppService)) {
    throw new IllegalArgumentException("SP entityID not registered or access denied: " + entityId);
}

Type guard

boolean isServiceUsable(SamlRegisteredService s) { return s != null && !s.getAccessStrategy().isServiceAccessAllowed(s, s.getServiceId()) == false; }

Try / catch

try {
    verifySamlRegisteredService(issuer, request);
} catch (UnauthorizedServiceException e) {
    LOGGER.error("SP not in registry or denied: {}", issuer, e);
    // return 403 / friendly error page
}

Prevention

When it happens

Trigger: Any SAML IdP profile request (SSO/SLO endpoints) whose issuer/entityID matches no SamlRegisteredService in the registry, or whose registered service's access strategy (e.g. disabled service, case-sensitive attribute/cas-allowlist rules in isServiceAccessAllowed) rejects the constructed web application service.

Common situations: SP entityID typo or case mismatch versus the service definition's serviceId pattern; service definition not loaded (JSON/YAML registry files not picked up, wrong regex); service marked disabled or expired; access strategy restricting by IP or relying-party attributes; changes after service registry refresh not yet propagated.

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

Appendix: source

Thrown at support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/AbstractSamlIdPProfileHandlerController.java:148

    }

    protected Optional<SamlRegisteredServiceMetadataAdaptor> getSamlMetadataFacadeFor(
        final SamlRegisteredService registeredService, final String entityId) {
        return SamlRegisteredServiceMetadataAdaptor.get(
            configurationContext.getSamlRegisteredServiceCachingMetadataResolver(), registeredService, entityId);
    }

    protected SamlRegisteredService verifySamlRegisteredService(final String serviceId,
                                                                final HttpServletRequest request) {
        if (StringUtils.isBlank(serviceId)) {
            throw UnauthorizedServiceException.denied("Could not verify/locate SAML registered service since no serviceId is provided");
        }
        val service = configurationContext.getWebApplicationServiceFactory().createService(serviceId, request);
        service.getAttributes().put(SamlProtocolConstants.PARAMETER_ENTITY_ID, CollectionUtils.wrapList(serviceId));
        LOGGER.debug("Checking service access in CAS service registry for [{}]", service);
        val registeredService = configurationContext.getServicesManager().findServiceBy(service, SamlRegisteredService.class);
        if (registeredService == null || !registeredService.getAccessStrategy().isServiceAccessAllowed(registeredService, service)) {
            LOGGER.warn("[{}] is not found in the registry or service access is denied.", serviceId);
            throw UnauthorizedServiceException.denied("Rejected: %s".formatted(serviceId));
        }
        LOGGER.debug("Located SAML service in the registry as [{}] with the metadata location of [{}]",
            registeredService.getServiceId(), registeredService.getMetadataLocation());
        return registeredService;
    }

    protected AuthenticatedAssertionContext buildCasAssertion(final Authentication authentication,
                                                              final Service service,
                                                              final RegisteredService registeredService,
                                                              final Map<String, List<Object>> attributesToCombine) throws Throwable {
        val context = RegisteredServiceAttributeReleasePolicyContext.builder()
            .registeredService(registeredService)
            .applicationContext(getConfigurationContext().getOpenSamlConfigBean().getApplicationContext())
            .service(service)
            .principal(authentication.getPrincipal())
            .build();
        val attributes = registeredService.getAttributeReleasePolicy().getAttributes(context);

View on GitHub (pinned to e7288fc434)