apereo/cas · error
Service [ ] is not authorized
Error message
Service [{}] is not authorized What it means
RegisteredServiceResponseHeadersEnforcementFilter.prepareFilterBeforeExecution logs 'Service [x] is not authorized' when the registered service access strategy enforcer reports an execution failure. The filter then responds HTTP 403 FORBIDDEN, stores the access exception as a request attribute, and skips adding the service's enforced response headers.
Solutions
- Inspect the request attribute ERROR_EXCEPTION / logs for the underlying access strategy exception to learn the denial reason.
- Fix the registered service definition: enable it, correct the service URL/pattern, or update the access strategy (authorized users, attributes, time window).
- Verify attribute release/attribute repository sources so required attributes are available at enforcement time.
- If the service should not be governed by this filter, adjust the filter/exclusion configuration rather than the service policy.
- Confirm the CAS node can reach backing stores (LDAP/Groovy policy) — unreachable sources can cause execution failure.
Example fix
// before: service JSON denies access
"accessStrategy": { "@class": "DefaultRegisteredServiceAccessStrategy", "enabled": false }
// after
"accessStrategy": { "@class": "DefaultRegisteredServiceAccessStrategy", "enabled": true, "ssoEnabled": true } Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check access before relying on response headers:
var audit = RegisteredServiceAccessStrategyAudit.builder()
.registeredService(registeredService).service(service).build();
if (accessEnforcer.execute(audit).isExecutionFailure()) {
LOGGER.warn("Service {} will be denied; fix access strategy", service.getId());
} Type guard
boolean isServiceAccessible(RegisteredService svc, Principal p) {
return svc.getAccessStrategy().isServiceAccessAllowed(svc, p);
} Prevention
- Audit registered services' accessStrategy settings (enabled, ssoEnabled, caseInsensitive, required attributes).
- Test service definitions in lower environments before promoting them to the registry.
- Log/inspect the exception stored in RequestDispatcher.ERROR_EXCEPTION for the denial root cause.
- Ensure backing attribute/policy stores (LDAP, Groovy, REST) are reachable at request time.
When it happens
Trigger: An incoming request matches a registered service, but RegisteredServiceAccessStrategyEnforcer.execute denies access — e.g. service disabled/unauthorized, access strategy case-sensitive name mismatch, unauthorized email/domain, missing required attributes, or time/day restrictions in the service definition.
Common situations: Service registry entry disabled or expired; attribute-based release policy denies the current principal; the service URL pattern matches but access strategy rules (delegated policy, LDAP-backed policy) fail; environment where the enforcer bean throws (upstream exceptions surfaced via accessResult.getException()).
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- Denied
- Cannot authorize principal
- Unauthorized account removal attempt
- Unknown authorization header type
- Resource-set owner does not match the authenticated profile
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/689d115565fb322c.
Report an issue: GitHub.
Appendix: source
Thrown at core/cas-server-core-web-api/src/main/java/org/apereo/cas/services/web/support/RegisteredServiceResponseHeadersEnforcementFilter.java:95
return Optional.empty();
}
val service = argumentExtractor.getObject().extractService(httpServletRequest);
if (service != null) {
LOGGER.trace("Attempting to resolve service for [{}]", service);
val resolved = authenticationRequestServiceSelectionStrategies.getObject().resolveService(service);
val servicesManager = servicesManagerProvider.getObject();
val registeredService = NumberUtils.isCreatable(resolved.getId())
? servicesManager.findServiceBy(Long.parseLong(resolved.getId()))
: servicesManager.findServiceBy(resolved);
val audit = AuditableContext
.builder()
.registeredService(registeredService)
.service(service)
.build();
val accessResult = registeredServiceAccessStrategyEnforcer.getObject().execute(audit);
if (accessResult.isExecutionFailure()) {
LOGGER.warn("Service [{}] is not authorized", resolved);
httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value());
httpServletRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION, accessResult.getException().orElse(null));
return Optional.empty();
}
return Optional.of(registeredService);
}
return Optional.empty();
}
@Override
protected void decideInsertContentSecurityPolicyHeader(final HttpServletResponse httpServletResponse,
final HttpServletRequest httpServletRequest,
final Optional<RegisteredService> result) {
val shouldInject = shouldHttpHeaderBeInjectedIntoResponse(result,
RegisteredServiceProperties.HTTP_HEADER_ENABLE_CONTENT_SECURITY_POLICY);
if (shouldInject.isPresent()) {
if (shouldInject.get()) {View on GitHub (pinned to e7288fc434)