apereo/cas · error · UnauthorizedServiceException
No security token could be retrieved for service
Error message
No security token could be retrieved for service [{}] and principal [{}] What it means
After ticket validation the callback controller asks the SecurityTokenServiceTokenFetcher to fetch a security token for the validated service and principal; the fetch returned empty, so the controller throws UnauthorizedServiceException.denied(). The token service could not issue/locate a token for this relying party.
Solutions
- Check the STS client configuration for the registered service (endpoint, token type, signing credentials)
- Verify the STS backend is reachable and healthy at fetch time; inspect earlier ERROR logs
- Confirm the registered service is a correctly configured WSFederationRegisteredService with token issuance enabled
- Retry the federation flow; if intermittent, look for STS/network timeouts
Defensive patterns
Strategy: try-catch
Validate before calling
if (getConfigContext().getSecurityTokenServiceTokenFetcher().fetch(service, principalId).isEmpty()) { /* token issuance will fail */ } Try / catch
try { return fetchSecurityTokenFromAssertion(assertion, service); }
catch (UnauthorizedServiceException e) { /* check STS config/reachability for this service */ throw e; } Prevention
- Validate STS endpoint, token type, and signing credentials per registered service
- Health-check the STS before deploying federation flows
- Inspect prior logs for the root cause of the empty token fetch
When it happens
Trigger: fetchSecurityTokenFromAssertion(): securityTokenServiceTokenFetcher.fetch(targetService, principal) yields Optional.empty() (typically because invokeSecurityTokenServiceForToken returned null) and the empty case triggers this warning plus the exception.
Common situations: Downstream STS endpoint unreachable or misconfigured so token issuance returns null; WS-Federation registered service missing required token configuration (token type, signing cert); principal id invalid for token claims; STS backend error swallowed into an empty Optional.
Understand the failure class
Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.
Related errors
- Security token linked to ticket
- Realm [ ] is not authorized for matching service [ ]
- Realm [ ] is not authorized for the identity provider realm…
- No groovy script cache manager is available to execute…
- Unable to determine the [WA] parameter
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/cd458b8e7cd318e1.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-ws-idp/src/main/java/org/apereo/cas/ws/idp/web/WSFederationValidateRequestCallbackController.java:110
val assertion = validateRequestAndBuildCasAssertion(response, request, fedRequest);
val securityTokenReq = getSecurityTokenFromRequest(request);
val securityToken = FunctionUtils.doIfNull(securityTokenReq,
Unchecked.supplier(() -> {
LOGGER.debug("No security token is yet available. Invoking security token service to issue token");
return fetchSecurityTokenFromAssertion(assertion, targetService);
}),
() -> securityTokenReq)
.get();
addSecurityTokenTicketToRegistry(request, securityToken);
val rpToken = produceRelyingPartyToken(request, targetService, fedRequest, securityToken, assertion);
return postResponseBackToRelyingParty(rpToken, fedRequest);
}
private SecurityToken fetchSecurityTokenFromAssertion(final TicketValidationResult assertion, final Service targetService) throws Throwable {
val principal = assertion.getPrincipal().getId();
val token = getConfigContext().getSecurityTokenServiceTokenFetcher().fetch(targetService, principal);
if (token.isEmpty()) {
LOGGER.warn("No security token could be retrieved for service [{}] and principal [{}]", targetService, principal);
throw UnauthorizedServiceException.denied("Denied: %s".formatted(targetService.getId()));
}
return token.get();
}
private void addSecurityTokenTicketToRegistry(final HttpServletRequest request,
final SecurityToken securityToken) throws Throwable {
LOGGER.trace("Creating security token as a ticket to CAS ticket registry...");
val ticketRegistry = getConfigContext().getTicketRegistry();
val tgt = CookieUtils.getTicketGrantingTicketFromRequest(getConfigContext().getTicketGrantingTicketCookieGenerator(),
ticketRegistry, request);
val serializedToken = SerializationUtils.serialize(securityToken);
val securityTokenTicketFactory = (SecurityTokenTicketFactory) getConfigContext().getTicketFactory().get(SecurityTokenTicket.class);
val ticket = securityTokenTicketFactory.create(tgt, serializedToken);
LOGGER.trace("Created security token ticket [{}]", ticket);
ticketRegistry.addTicket(ticket);
LOGGER.trace("Added security token as a ticket to CAS ticket registry...");View on GitHub (pinned to e7288fc434)