apereo/cas · warning
Provided client id [ ] cannot be matched against a service…
Error message
Provided client id [{}] cannot be matched against a service definition What it means
OAuth20RevocationRequestValidator.validate() resolves the clientId from the revocation request and looks it up in the ServicesManager. When no registered OAuth service matches the clientId, it warns and returns false, so the RFC 7009 token revocation request is refused.
Solutions
- Register the clientId as an OAuth service definition in the CAS services registry and deploy/reload it.
- Verify the CAS instance is talking to the intended services registry for that environment.
- Check the clientId in the request (parameter or Basic auth header) for typos or stale values.
- Confirm the service is enabled and its clientId actually matches what the client sends.
Example fix
// before (registry)
{"@class":"...OAuthRegisteredService","serviceId":"https://app.example.com","clientId":"wrongId"}
// after
{"@class":"...OAuthRegisteredService","serviceId":"https://app.example.com","clientId":"correct-client-id"} Defensive patterns
Strategy: validation
Validate before calling
const svc = await servicesRegistry.findByClientId(clientId);
if (!svc) {
throw new Error(`clientId ${clientId} is not registered in the CAS services registry`);
} Prevention
- Register every client before enabling it against a CAS environment
- Sync services registry across environments deliberately; don't assume parity
- Verify env-specific CAS endpoints in client config
When it happens
Trigger: A POST to the OAuth revocation endpoint with a client_id (from parameter or Basic auth) that has no corresponding registered service in the CAS services registry — unregistered client, wrong environment's registry, or typo.
Common situations: Client registered in production but pointing at a staging CAS; services registry not loaded/synced (JSON file missing, JDBC empty); clientId misspelled; registry entry deleted or disabled so it no longer matches.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- unauthorized_client
- Registered service access is not allowed for service…
- The service definition file could not be saved at
- Subject token type is not supported
- Actor token type is not supported
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/2397f23105908271.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/token/OAuth20RevocationRequestValidator.java:45
@Getter
@Setter
public class OAuth20RevocationRequestValidator implements OAuth20TokenRequestValidator {
private final ServicesManager servicesManager;
private final SessionStore sessionStore;
private final OAuth20RequestParameterResolver requestParameterResolver;
private int order = Ordered.LOWEST_PRECEDENCE;
@Override
public boolean validate(final WebContext context) {
val callContext = new CallContext(context, sessionStore);
val clientId = requestParameterResolver.resolveClientIdAndClientSecret(callContext).getLeft();
val registeredService = OAuth20Utils.getRegisteredOAuthServiceByClientId(this.servicesManager, clientId);
if (registeredService == null) {
LOGGER.warn("Provided client id [{}] cannot be matched against a service definition", clientId);
return false;
}
return true;
}
@Override
public boolean supports(final WebContext context) {
val token = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.TOKEN)
.map(String::valueOf).orElse(StringUtils.EMPTY);
if (StringUtils.isBlank(token)) {
return false;
}
val callContext = new CallContext(context, sessionStore);
val clientId = requestParameterResolver.resolveClientIdAndClientSecret(callContext).getLeft();
return StringUtils.isNotBlank(clientId);
}
}View on GitHub (pinned to e7288fc434)