{"record":{"id":"10db76c79fb2c806","repo":"apereo/cas","slug":"unable-to-locate-registered-service-for-clientid","errorCode":null,"errorMessage":"Unable to locate registered service for clientId [{}] or redirectUri [{}]","messagePattern":"Unable to locate registered service for clientId \\[(.+?)\\] or redirectUri \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/response/accesstoken/ext/AccessTokenAuthorizationCodeGrantRequestExtractor.java","lineNumber":132,"sourceCode":"            .resolveRequestParameter(context, getOAuthParameterName()).orElse(StringUtils.EMPTY);\n    }\n\n    protected OAuth20Token getOAuthTokenFromRequest(final WebContext context) {\n        val id = getOAuthParameter(context);\n        return getConfigurationContext().getObject().getTicketRegistry().getTicket(id, OAuth20Token.class);\n    }\n\n    protected OAuthRegisteredService getOAuthRegisteredServiceBy(final WebContext context) {\n        val configurationContext = getConfigurationContext().getObject();\n        val callContext = new CallContext(context, configurationContext.getSessionStore());\n        val clientId = configurationContext.getRequestParameterResolver()\n            .resolveClientIdAndClientSecret(callContext).getLeft();\n        val redirectUri = getRegisteredServiceIdentifierFromRequest(context);\n        val registeredService = StringUtils.isNotBlank(clientId)\n            ? OAuth20Utils.getRegisteredOAuthServiceByClientId(configurationContext.getServicesManager(), clientId)\n            : OAuth20Utils.getRegisteredOAuthServiceByRedirectUri(configurationContext.getServicesManager(), redirectUri);\n        FunctionUtils.doIf(registeredService == null,\n            param -> LOGGER.warn(\"Unable to locate registered service for clientId [{}] or redirectUri [{}]\", clientId, redirectUri),\n            ex -> LOGGER.debug(\"Located registered service [{}]\", registeredService)).accept(registeredService);\n        return registeredService;\n    }\n\n    protected Ticket fetchTicketGrantingTicket(final OAuth20Token token) {\n        try {\n            if (token.getTicketGrantingTicket() != null) {\n                val id = token.getTicketGrantingTicket().getId();\n                val configurationContext = getConfigurationContext().getObject();\n                val ticketGrantingTicket = configurationContext.getTicketRegistry().getTicket(id, TicketGrantingTicket.class);\n\n                FunctionUtils.doUnchecked(_ -> {\n                    token.assignTicketGrantingTicket(ticketGrantingTicket);\n                    configurationContext.getTicketRegistry().updateTicket(token);\n                });\n\n                return ticketGrantingTicket;\n            }","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/response/accesstoken/ext/AccessTokenAuthorizationCodeGrantRequestExtractor.java#L114-L150","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before (services/missing-client.json absent)\ncurl -u myclient:secret -d 'grant_type=authorization_code&code=...' https://cas/oauth2.0/token\n// after\n// services/myclient.json:\n// {\"@class\":\"org.apereo.cas.support.oauth.services.OAuthRegisteredService\",\"clientId\":\"myclient\",\"clientSecret\":\"secret\",\"serviceId\":\"^https://app.example.org/.*\",\"name\":\"App\",\"id\":1}\ncurl -u myclient:secret -d 'grant_type=authorization_code&code=...&redirect_uri=https://app.example.org/cb' https://cas/oauth2.0/token","handlingStrategy":"validation","validationCode":"// pre-flight: ensure the service is registered before making token calls\nconst svc = await servicesManager.findServiceBy(clientId);\nif (!svc) throw new Error(`No CAS OAuth service registered for clientId ${clientId}`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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)."],"tags":["oauth2","service-registry","client-not-registered","configuration"],"backgroundTag":"resource-not-found","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}