apereo/cas · warning
Unable to locate registered service for clientId
Error message
Unable to locate registered service for clientId [{}] or redirectUri [{}] What it means
When extracting an access token via the authorization-code grant, CAS resolves the OAuth registered service using the client_id from the request (or, if blank, the redirect_uri). If ServicesManager contains no matching registered OAuth service, the extractor logs this warning and returns null, aborting the token grant.
Solutions
- Register (or fix) the OAuth service in the service registry so its clientId matches the request and its serviceId pattern matches the redirect_uri.
- Check the service registry storage (JSON files, JPA, Mongo...) actually contains the service and that CAS has loaded it (watch the registry for changes/restart).
- Verify the exact client_id sent by the client (Basic auth vs form param) and correct typos/case.
- If relying on redirect_uri matching, ensure the redirect URI in the request is identical to what the serviceId regex accepts.
Example fix
// before (services/missing-client.json absent)
curl -u myclient:secret -d 'grant_type=authorization_code&code=...' https://cas/oauth2.0/token
// after
// services/myclient.json:
// {"@class":"org.apereo.cas.support.oauth.services.OAuthRegisteredService","clientId":"myclient","clientSecret":"secret","serviceId":"^https://app.example.org/.*","name":"App","id":1}
curl -u myclient:secret -d 'grant_type=authorization_code&code=...&redirect_uri=https://app.example.org/cb' https://cas/oauth2.0/token Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: ensure the service is registered before making token calls
const svc = await servicesManager.findServiceBy(clientId);
if (!svc) throw new Error(`No CAS OAuth service registered for clientId ${clientId}`); Prevention
- Keep service registry files under version control and deploy them with the app.
- Match redirect_uri exactly against the service's serviceId regex.
- Verify registry contents after startup/refresh (CAS services management endpoints).
When it happens
Trigger: A token request to /oauth2.0/token with grant_type=authorization_code where getOAuthRegisteredServiceBy finds no service: clientId (resolved from basic auth or form params) matches no registered service, or clientId is blank and the redirect_uri matches no registered service's serviceId pattern.
Common situations: Service not registered in the CAS service registry (JSON registry file missing/not deployed/registry not refreshed); client_id typo; redirect_uri not matching the service's serviceId regex; registry loading delayed at startup; service defined but not marked as an OAuth client (missing clientId/secret properties).
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
- Registered service template definition
- Skipped registration of
- No user can be accepted because none is defined
- Not all requested multifactor providers could be found…
- Cookie name is undefined
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/10db76c79fb2c806.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/response/accesstoken/ext/AccessTokenAuthorizationCodeGrantRequestExtractor.java:132
.resolveRequestParameter(context, getOAuthParameterName()).orElse(StringUtils.EMPTY);
}
protected OAuth20Token getOAuthTokenFromRequest(final WebContext context) {
val id = getOAuthParameter(context);
return getConfigurationContext().getObject().getTicketRegistry().getTicket(id, OAuth20Token.class);
}
protected OAuthRegisteredService getOAuthRegisteredServiceBy(final WebContext context) {
val configurationContext = getConfigurationContext().getObject();
val callContext = new CallContext(context, configurationContext.getSessionStore());
val clientId = configurationContext.getRequestParameterResolver()
.resolveClientIdAndClientSecret(callContext).getLeft();
val redirectUri = getRegisteredServiceIdentifierFromRequest(context);
val registeredService = StringUtils.isNotBlank(clientId)
? OAuth20Utils.getRegisteredOAuthServiceByClientId(configurationContext.getServicesManager(), clientId)
: OAuth20Utils.getRegisteredOAuthServiceByRedirectUri(configurationContext.getServicesManager(), redirectUri);
FunctionUtils.doIf(registeredService == null,
param -> LOGGER.warn("Unable to locate registered service for clientId [{}] or redirectUri [{}]", clientId, redirectUri),
ex -> LOGGER.debug("Located registered service [{}]", registeredService)).accept(registeredService);
return registeredService;
}
protected Ticket fetchTicketGrantingTicket(final OAuth20Token token) {
try {
if (token.getTicketGrantingTicket() != null) {
val id = token.getTicketGrantingTicket().getId();
val configurationContext = getConfigurationContext().getObject();
val ticketGrantingTicket = configurationContext.getTicketRegistry().getTicket(id, TicketGrantingTicket.class);
FunctionUtils.doUnchecked(_ -> {
token.assignTicketGrantingTicket(ticketGrantingTicket);
configurationContext.getTicketRegistry().updateTicket(token);
});
return ticketGrantingTicket;
}View on GitHub (pinned to e7288fc434)