{"record":{"id":"34159fb0539e40cd","repo":"apereo/cas","slug":"unauthorized-client","errorCode":"unauthorized_client","errorMessage":"Client is not allowed to use the [%s] response type","messagePattern":"Client is not allowed to use the \\[(.+?)\\] response type","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidator.java","lineNumber":51,"sourceCode":"        final ServicesManager servicesManager,\n        final ServiceFactory<WebApplicationService> webApplicationServiceServiceFactory,\n        final AuditableExecution registeredServiceAccessStrategyEnforcer,\n        final OAuth20RequestParameterResolver requestParameterResolver) {\n        super(servicesManager, webApplicationServiceServiceFactory,\n            registeredServiceAccessStrategyEnforcer, requestParameterResolver);\n    }\n\n    @Override\n    public boolean validate(final WebContext context) {\n        val clientIdResult = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.CLIENT_ID);\n        return clientIdResult\n            .map(this::getRegisteredServiceByClientId)\n            .filter(Objects::nonNull)\n            .map(registeredService -> {\n                if (!requestParameterResolver.isAuthorizedResponseTypeForService(context, registeredService)) {\n                    val responseTypeResult = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.RESPONSE_TYPE);\n                    val msg = String.format(\"Client is not allowed to use the [%s] response type\", responseTypeResult.orElse(\"unknown\"));\n                    LOGGER.warn(msg);\n                    setErrorDetails(context, OAuth20Constants.UNAUTHORIZED_CLIENT, msg, true);\n                    return false;\n                }\n                return true;\n            })\n            .orElse(false);\n    }\n\n    @Override\n    public boolean supports(final WebContext context) throws Throwable {\n        if (preValidate(context)) {\n            val responseType = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.RESPONSE_TYPE)\n                .map(String::valueOf)\n                .orElse(StringUtils.EMPTY);\n            LOGGER.debug(\"Requested response type is [{}]\", responseType);\n            return getSupportedResponseTypes()\n                .stream()\n                .anyMatch(allowedType -> OAuth20Utils.isResponseType(responseType, allowedType));","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/validator/authorization/OAuth20AuthorizationCodeResponseTypeAuthorizationRequestValidator.java#L33-L69","documentation":"Even when a response_type value is globally supported, the registered OAuth service must be permitted to use it. DefaultOAuth20RequestParameterResolver.isAuthorizedResponseTypeForService checks the service's supported grant types / response-type configuration; if the code flow's response_type is not authorized for this client, CAS fails the authorization request with error=unauthorized_client.","triggerScenarios":"GET /oauth2.0/authorize?response_type=code&client_id=X where registered service X does not list the authorization-code grant type (or its supportedGrantTypes/responseTypes config excludes it), or a custom OAuth20RequestParameterResolver bean denies it.","commonSituations":"Service registered for implicit/client-credentials only but client initiates code flow; service definition missing supportedGrantTypes after migration from an older CAS where defaults were broader; JSON service exported without the supportedGrantTypes/supportedResponseTypes fields.","solutions":["Set the service's supported grant types to include AUTHORIZATION_CODE (e.g. supportedGrantTypes in the registered service definition) via the service registry or management app.","Confirm no custom OAuth20RequestParameterResolver bean overrides isAuthorizedResponseTypeForService in a way that rejects code for this service.","Re-export/recreate the registered service JSON so grant-type fields survive upgrades; check cas.authn.oauth defaults if relying on global fallback.","Use the response_type/grant type actually allowed for the client (e.g. token for implicit-only clients)."],"exampleFix":"// before (registered service JSON)\n\"supportedGrantTypes\": [\"CLIENT_CREDENTIALS\"]\n// after\n\"supportedGrantTypes\": [\"AUTHORIZATION_CODE\", \"REFRESH_TOKEN\"]","handlingStrategy":"validation","validationCode":"// before initiating code flow, confirm the client's registry entry permits it\nif (!service.supportedGrantTypes?.includes('AUTHORIZATION_CODE')) {\n  throw new Error('Client not authorized for authorization_code response type');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When registering an OAuth service in CAS, always set supportedGrantTypes/supportedResponseTypes explicitly to the flows the client uses.","Audit service-registry JSON after CAS upgrades for dropped grant-type fields.","Keep one service definition per client rather than sharing broad grant types."],"tags":["oauth","response-type","unauthorized-client","service-registry"],"backgroundTag":"permission-denied","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"}