apereo/cas · error
Unable to resolve federated service
Error message
Unable to resolve federated service [{}] What it means
OpenIdFederationAuthorizationCodeResponseTypeAuthorizationRequestValidator.resolveAndSaveFederatedService failed to resolve a federated OP/client from its entity ID via trust-chain resolution. The trust chain (entity statements from entity configuration endpoints) could not be validated or fetched, so no federated service is registered and the authorization request is rejected with 'Unable to resolve federated service [clientId]'.
Solutions
- Verify the client's entity configuration URL (https://host/.well-known/openid-federation) is reachable from CAS and returns a valid entity statement.
- Configure the CAS OIDC federation trust anchors so the entity's trust chain terminates at an accepted anchor.
- Register the relying party explicitly as a service if federation is not intended for it.
- Check logs for the underlying exception via LoggingUtils to distinguish network vs signature/trust failures.
Example fix
// before: entity unknown to any trust anchor // cas.authn.oidc.federation.trust-anchors= (empty) // after // cas.authn.oidc.federation.trust-anchors=https://trusted-anchor.example.org/.well-known/openid-federation
Defensive patterns
Strategy: validation
Validate before calling
// Verify entity configuration reachability before relying on federation
URL u = URI.create("https://client.example.org/.well-known/openid-federation").toURL();
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setConnectTimeout(5000);
if (c.getResponseCode() != 200) throw new IllegalStateException("Entity config unreachable"); Try / catch
// Trust-chain resolution can fail transiently
try {
Optional<OAuthRegisteredService> svc = resolver.resolveTrustChains(clientId);
svc.orElseThrow(() -> new IllegalArgumentException("Unresolvable federated client " + clientId));
} catch (Exception e) {
LOGGER.warn("Federation resolution failed for {}", clientId, e);
} Prevention
- Pre-register critical relying parties explicitly instead of relying solely on dynamic federation
- Monitor entity configuration endpoints of federation members
- Keep trust anchors current and test chain resolution after anchor key rotation
When it happens
Trigger: An authorization request arrives with a clientId that is not registered locally, so CAS calls resolveMissingFederatedService or refreshes a temporary federation service; oidcFederationTrustChainResolver.resolveTrustChains(clientId) throws or returns empty because the entity's .well-known/openid-federation endpoint is unreachable, the trust chain lacks a trust anchor, or signatures fail validation.
Common situations: Federation entity's entity configuration endpoint down or misconfigured DNS/TLS; trust anchors not configured in CAS to cover the entity; expired entity statement keys; trying federation without the federation feature properly enabled.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- No (successful) logout response received from the url
- not in allowed range.
- Unexpected LDAP error
- Failed to acquire access token
- JWKS cannot contain expressions
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/380ab0febef9b93d.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-federation/src/main/java/org/apereo/cas/oidc/federation/validator/OpenIdFederationAuthorizationCodeResponseTypeAuthorizationRequestValidator.java:89
if (!shouldRefreshTemporaryFederationService(registeredService)) {
return registeredService;
}
val serviceLock = SERVICE_LOCKS.computeIfAbsent(clientId, key -> new ReentrantLock());
serviceLock.lock();
try {
return resolveAndSaveFederatedService(clientId).orElse(registeredService);
} finally {
serviceLock.unlock();
}
}
private Optional<OAuthRegisteredService> resolveAndSaveFederatedService(final String clientId) {
try {
val resolvedService = oidcFederationTrustChainResolver.resolveTrustChains(clientId);
LOGGER.debug("Resolved service: [{}]", resolvedService);
return resolvedService.map(service -> (OAuthRegisteredService) getServicesManager().save(service));
} catch (final Exception e) {
LoggingUtils.warn(LOGGER, "Unable to resolve federated service [" + clientId + "]", e);
return Optional.empty();
}
}
private static boolean shouldRefreshTemporaryFederationService(final OAuthRegisteredService registeredService) {
if (!registeredService.getProperties().containsKey(OidcFederationDefaultTrustChainResolver.TEMPORARY_OPENIDFEDERATION_SERVICE)) {
return false;
}
val expirationDate = registeredService.getExpirationPolicy().getExpirationDate();
val expiration = DateTimeUtils.zonedDateTimeOf(expirationDate);
val refresh = expiration.minus(SERVICE_EXPIRATION_REFRESH_WINDOW).isBefore(ZonedDateTime.now(Clock.systemUTC()));
LOGGER.debug("Should refresh: [{}] upfront: [{}]", registeredService, refresh);
return refresh;
}
private static boolean isFederatedEntityId(final String clientId) {
if (StringUtils.isBlank(clientId)) {
return false;View on GitHub (pinned to e7288fc434)