apereo/cas · warning
e.getMessage()
Error message
e.getMessage()
What it means
RegisteredServiceAccessEndpoint.authorize() authenticates a user via header/body credentials and, for any unexpected Throwable (not an AuthenticationException), logs the exception and returns HTTP 403 with e.getMessage() as the body. The message is the raw exception text of an internal failure during the access-check flow, so it is intentionally opaque and depends entirely on what went wrong downstream (service lookup, credential building, etc.).
Solutions
- Read the returned message body and the correlated WARN log via LoggingUtils to identify the underlying Throwable
- Fix the root cause in the referenced handler/service configuration (e.g. register the required AuthenticationHandler or ServicesManager bean)
- If the intended failure is bad credentials, ensure it surfaces as AuthenticationException so it maps to 401 instead of 403
- Call the endpoint with valid username/password headers or body parameters matching the configured credential extractor
Example fix
// before: opaque 403 from generic Throwable
ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
// after: catch known cases explicitly
catch (final CredentialNotSupportedException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
} Defensive patterns
Strategy: try-catch
Validate before calling
// client-side precheck
if (!username || !password) throw new Error('credentials required for /registeredServiceAccess'); Type guard
function isAuthError(status) { return status === 401; } Try / catch
try { val resp = authorize(u, p, svc); if (resp.statusCode == 403) log(resp.body); }
catch (Exception e) { log('access check failed', e); } Prevention
- Send credentials exactly as the configured header/body extractor expects
- Confirm the target registered service exists and is enabled before calling
- Watch CAS logs for the LoggingUtils WARN to catch the true root cause early
When it happens
Trigger: Calling the /registeredServiceAccess REST endpoint (or authorize() directly) with credentials whose authentication path throws a non-AuthenticationException Throwable, e.g. service lookup failure, NPE in buildAuthentication, or a configuration error in the underlying AuthenticationManager.
Common situations: Calling the endpoint without the CAS reports module fully configured; passing a serviceId that fails service creation; missing beans for the authentication handler chain; network/DB issues behind a custom authentication handler.
Related errors
- Could not authenticate forbidden account for
- Unable to accept response status
- No credentials can be extracted to authenticate the REST…
- Unable to extract credentials for multifactor authentication
- Could not authenticate account for
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/f9cb610787905320.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-reports-core/src/main/java/org/apereo/cas/web/report/RegisteredServiceAccessEndpoint.java:119
val service = authenticationServiceSelectionPlan.getObject().resolveService(argumentExtractor.getObject().extractService(request));
val registeredService = servicesManager.getObject().findServiceBy(service);
RegisteredServiceAccessStrategyUtils.ensureServiceAccessIsAllowed(service, registeredService);
val authentication = buildAuthentication(request.getParameter("username"), request.getParameter("password"), service);
val accessRequest = AuditableContext
.builder()
.service(service)
.authentication(authentication)
.registeredService(registeredService)
.build();
val accessResult = registeredServiceAccessStrategyEnforcer.getObject().execute(accessRequest);
return accessResult.isExecutionFailure()
? ResponseEntity.status(HttpStatus.FORBIDDEN).body("Access to %s is denied".formatted(service.getId()))
: ResponseEntity.ok(Map.of("registeredService", registeredService, "authentication", authentication, "service", service));
} catch (final AuthenticationException e) {
LoggingUtils.warn(LOGGER, e);
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
} catch (final Throwable e) {
LoggingUtils.warn(LOGGER, e);
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
}
}
private Authentication buildAuthentication(final String username, final String password,
final Service selectedService) throws Throwable {
if (StringUtils.isNotBlank(password)) {
val credential = new UsernamePasswordCredential(username, password);
val result = authenticationSystemSupport.getObject().finalizeAuthenticationTransaction(selectedService, credential);
return result.getAuthentication();
}
val principal = principalResolver.getObject().resolve(new BasicIdentifiableCredential(username),
Optional.of(principalFactory.getObject().createPrincipal(username)),
Optional.empty(), Optional.of(selectedService));
return DefaultAuthenticationBuilder.newInstance().setPrincipal(principal).build();
}
}View on GitHub (pinned to e7288fc434)