apereo/cas · warning
Response type not authorized for service
Error message
Response type not authorized for service: [{}] not listed in supported response types: [{}] What it means
DefaultOAuth20RequestParameterResolver.isAuthorizedResponseTypeForService() compares the request's response_type against the registered service's supportedResponseTypes. When the list is non-empty but does not contain the requested response type, it warns and returns false, so the OAuth request (e.g., authorize) is denied as the requested response type is not authorized for that service.
Solutions
- Add the response_type the client requests (e.g., "code") to the service's supportedResponseTypes.
- Ensure the client sends the response_type parameter on authorize requests.
- Reload the services registry after editing the definition.
- Audit each client app's expected flow (code vs implicit) and align service definitions accordingly.
Example fix
// before (service JSON) "supportedResponseTypes": ["token"] // after "supportedResponseTypes": ["code", "token"]
Defensive patterns
Strategy: validation
Validate before calling
const responseType = params.response_type;
if (!responseType || !service.supportedResponseTypes?.some(t => t.toLowerCase() === responseType.toLowerCase())) {
throw new Error(`response_type '${responseType}' not authorized for this service`);
} Type guard
function isResponseTypeAuthorized(service, responseType) {
return typeof responseType === 'string' &&
Array.isArray(service.supportedResponseTypes) &&
service.supportedResponseTypes.some(t => t.toLowerCase() === responseType.toLowerCase());
} Prevention
- Always send response_type on authorize requests
- Align supportedResponseTypes with each client's flow (code vs token/id_token)
- Case-insensitively match but prefer exact registered values
When it happens
Trigger: An authorize/device request with response_type=code (or token/id_token variants) for a service whose supportedResponseTypes excludes that value, or the parameter is missing (resolves to empty string) while the list is non-empty.
Common situations: Service JSON defines supportedResponseTypes ["token"] but client requests code; response_type parameter omitted entirely by the client; service entry copied from another app with a narrower type list; CAS version upgrade enforcing response-type matching.
Related errors
- unsupported_response_type
- unauthorized_client
- Access token request cannot be validated for grant type
- Response type [ ] or grant type [ ] is not supported.
- Requested grant type
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/cdc207e355b71db1.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oauth-core-api/src/main/java/org/apereo/cas/support/oauth/web/DefaultOAuth20RequestParameterResolver.java:207
@Override
public boolean isAuthorizedGrantTypeForService(final WebContext context,
final OAuthRegisteredService registeredService) {
val grantType = resolveRequestParameter(context, OAuth20Constants.GRANT_TYPE)
.map(String::valueOf).orElse(StringUtils.EMPTY);
return OAuth20RequestParameterResolver.isAuthorizedGrantTypeForService(grantType, registeredService);
}
@Override
public boolean isAuthorizedResponseTypeForService(final WebContext context,
final OAuthRegisteredService registeredService) {
if (registeredService.getSupportedResponseTypes() != null && !registeredService.getSupportedResponseTypes().isEmpty()) {
val responseType = resolveRequestParameter(context, OAuth20Constants.RESPONSE_TYPE)
.map(String::valueOf).orElse(StringUtils.EMPTY);
if (registeredService.getSupportedResponseTypes().stream().anyMatch(s -> s.equalsIgnoreCase(responseType))) {
return true;
}
LOGGER.warn("Response type not authorized for service: [{}] not listed in supported response types: [{}]",
responseType, registeredService.getSupportedResponseTypes());
return false;
}
LOGGER.warn("Registered service [{}] does not define any authorized/supported response types. "
+ "It is STRONGLY recommended that you authorize and assign response types to the service definition. "
+ "While just a warning for now, this behavior will be enforced by CAS in future versions.", registeredService.getName());
return true;
}
@Override
public Pair<String, String> resolveClientIdAndClientSecret(final CallContext callContext) {
val extractor = new BasicAuthExtractor();
val upcResult = extractor.extract(callContext);
if (upcResult.isPresent()) {
val upc = (UsernamePasswordCredentials) upcResult.get();
return Pair.of(upc.getUsername(), upc.getPassword());
}
val clientId = resolveRequestParameter(callContext.webContext(), OAuth20Constants.CLIENT_ID)View on GitHub (pinned to e7288fc434)