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

  1. Register (or fix) the OAuth service in the service registry so its clientId matches the request and its serviceId pattern matches the redirect_uri.
  2. 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).
  3. Verify the exact client_id sent by the client (Basic auth vs form param) and correct typos/case.
  4. 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

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


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)