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

  1. Read the returned message body and the correlated WARN log via LoggingUtils to identify the underlying Throwable
  2. Fix the root cause in the referenced handler/service configuration (e.g. register the required AuthenticationHandler or ServicesManager bean)
  3. If the intended failure is bad credentials, ensure it surfaces as AuthenticationException so it maps to 401 instead of 403
  4. 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

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


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)