apereo/cas · error · UnauthorizedServiceException
Realm [ ] is not authorized for matching service [ ]
Error message
Realm [{}] is not authorized for matching service [{}] What it means
The wtrealm value presented in the WS-Federation request is blank or does not (case-insensitively) match the realm configured on the matching WSFederationRegisteredService, so the request is rejected with UnauthorizedServiceException.denied().
Solutions
- Set the registered service's realm to exactly the wtrealm the application sends (or fix the app's wtrealm)
- Compare the logged realm and service values for whitespace/scheme/path differences and correct them
- Verify service matching resolves the intended WSFederationRegisteredService (serviceId pattern not too greedy)
- Re-test with a fresh sign-in request after fixing the realm
Example fix
// before "realm": "https://app.example.com/" (app sends https://app.example.com) // after "realm": "https://app.example.com"
Defensive patterns
Strategy: validation
Validate before calling
if (fedRequest.wtrealm() == null || !fedRequest.wtrealm().equalsIgnoreCase(registeredService.getRealm())) {
throw new IllegalArgumentException("wtrealm does not match registered service realm");
} Try / catch
try { controller.findAndValidateFederationRequestForRegisteredService(service, request); }
catch (UnauthorizedServiceException e) { /* inspect realm config of app and CAS service */ } Prevention
- Copy the exact wtrealm from the application's federation request into the registered service
- Avoid scheme/trailing-slash differences between app and service realm
- Verify service-matching patterns resolve the intended service
When it happens
Trigger: findAndValidateFederationRequestForRegisteredService() compares fedRequest.wtrealm() against svc.getRealm() via Strings.CI.equals and fails, then throws UnauthorizedServiceException.
Common situations: Application's wtrealm/Realm query parameter differs from the realm set on the CAS registered service (trailing slash, http vs https host, case handled only loosely); service resolution matched a different/wrong registered service; app upgraded and changed its realm identifier.
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
- Realm [ ] is not authorized for the identity provider realm…
- No security token could be retrieved for service
- No groovy script cache manager is available to execute…
- Unable to determine the [WA] parameter
- The authentication request is not recognized
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/7916dad087f845ca.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-ws-idp/src/main/java/org/apereo/cas/ws/idp/web/BaseWSFederationRequestController.java:130
return true;
}
val ttlMs = TimeUnit.MINUTES.toMillis(ttl);
if (ttlMs > 0) {
val createdDate = idpToken.getCreated();
if (createdDate != null) {
val expiryDate = new Date(createdDate.toEpochMilli() + ttlMs);
return expiryDate.before(new Date());
}
}
return false;
}
protected WSFederationRegisteredService findAndValidateFederationRequestForRegisteredService(final Service targetService,
final WSFederationRequest fedRequest) {
val svc = getWsFederationRegisteredService(targetService);
if (StringUtils.isBlank(fedRequest.wtrealm()) || !Strings.CI.equals(fedRequest.wtrealm(), svc.getRealm())) {
LOGGER.warn("Realm [{}] is not authorized for matching service [{}]", fedRequest.wtrealm(), svc);
throw UnauthorizedServiceException.denied("Rejected: %s".formatted(svc.getRealm()));
}
val idp = configContext.getCasProperties().getAuthn().getWsfedIdp().getIdp();
if (!Strings.CI.equals(idp.getRealm(), svc.getRealm())) {
LOGGER.warn("Realm [{}] is not authorized for the identity provider realm [{}]", fedRequest.wtrealm(), idp.getRealm());
throw UnauthorizedServiceException.denied("Rejected: %s".formatted(svc.getRealm()));
}
return svc;
}
protected WSFederationRegisteredService getWsFederationRegisteredService(final Service targetService) {
val svc = configContext.getServicesManager().findServiceBy(targetService, WSFederationRegisteredService.class);
RegisteredServiceAccessStrategyUtils.ensureServiceAccessIsAllowed(targetService, svc);
return svc;
}
/**View on GitHub (pinned to e7288fc434)