apereo/cas · warning
Registered service access is not allowed for service…
Error message
Registered service access is not allowed for service definition for client id [{}] What it means
OAuth20DeviceCodeResponseTypeRequestValidator.validate() rejects the device-authorization request when the registered OAuth service cannot be accessed or when neither the response type nor the grant type is authorized for the client. Any exception thrown by ensureServiceAccessIsAllowed (or the validator chain) is caught and converted into this warning and a `false` result, so the device code flow is denied early.
Solutions
- Inspect the registered service definition for the given clientId in the services registry (JSON/JDBC/etc.) and confirm the access strategy allows access (enabled, not expired, valid IP/environment).
- Add the device-code response type and grant type to the service's supportedResponseTypes/supportedGrantTypes lists.
- If access should be denied intentionally, no action: CAS correctly rejects it; fix the client to use a registered, authorized clientId.
- Reload/redeploy the service registry after edits so ServicesManager picks up the new definition.
Example fix
// before (service JSON) "supportedGrantTypes": [], "supportedResponseTypes": [] // after "supportedGrantTypes": ["urn:ietf:params:oauth:grant-type:device_code"], "supportedResponseTypes": ["device_token"]
Defensive patterns
Strategy: validation
Validate before calling
// before calling the device endpoint, verify service access in the registry
const svc = services.find(s => s.clientId === clientId);
if (!svc || !svc.enabled || new Date(svc.expirationDate) < new Date()) {
throw new Error(`Service for clientId ${clientId} is not accessible`);
}
if (!svc.supportedGrantTypes.includes('urn:ietf:params:oauth:grant-type:device_code')) {
throw new Error('device_code grant not authorized for service');
} Type guard
function isAccessibleService(svc) {
return !!svc && svc.enabled === true &&
(!svc.expirationDate || new Date(svc.expirationDate) > new Date());
} Prevention
- Always populate supportedGrantTypes and supportedResponseTypes on new service definitions
- Keep service expiration dates current; use no-expiration for long-lived machine clients
- Test device flow after every services-registry change
When it happens
Trigger: A device-authorization request arrives with a clientId whose registered service is disabled, expired, outside its valid date window, or lacks access from the client's IP address; alternatively the service does not authorize the requested response type/grant type and neither `validResponseType` nor `validGrantType` evaluates true.
Common situations: Service definition created but left `enabled: false` or with an expiration date in the past; environment/IP allowlist restrictions on the service; supportedResponseTypes or supportedGrantTypes not configured on the service definition; wrong clientId sent by the device client.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- unauthorized_client
- Provided client id [ ] cannot be matched against a 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/7d452fe1a8fe890d.
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/OAuth20DeviceCodeResponseTypeRequestValidator.java:63
.map(String::valueOf).orElse(StringUtils.EMPTY);
val grantType = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.GRANT_TYPE)
.map(String::valueOf).orElse(StringUtils.EMPTY);
val validResponseType = OAuth20Utils.isResponseType(responseType, OAuth20ResponseTypes.DEVICE_CODE);
val validGrantType = OAuth20Utils.isGrantType(grantType, OAuth20GrantTypes.DEVICE_CODE);
if (!validResponseType && !validGrantType) {
LOGGER.warn("Response type [{}] or grant type [{}] is not supported.", responseType, grantType);
return false;
}
val clientId = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.CLIENT_ID).orElse(StringUtils.EMPTY);
return FunctionUtils.doAndHandle(() -> {
val registeredService = Objects.requireNonNull(OAuth20Utils.getRegisteredOAuthServiceByClientId(this.servicesManager, clientId));
RegisteredServiceAccessStrategyUtils.ensureServiceAccessIsAllowed(registeredService);
return (validResponseType && requestParameterResolver.isAuthorizedResponseTypeForService(context, registeredService))
|| (validGrantType && requestParameterResolver.isAuthorizedGrantTypeForService(context, registeredService));
}, t -> {
LOGGER.warn("Registered service access is not allowed for service definition for client id [{}]", clientId);
return false;
}).get();
}
@Override
public boolean supports(final WebContext context) {
val responseType = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.RESPONSE_TYPE)
.map(String::valueOf).orElse(StringUtils.EMPTY);
val grantType = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.GRANT_TYPE)
.map(String::valueOf).orElse(StringUtils.EMPTY);
val clientId = requestParameterResolver.resolveRequestParameter(context, OAuth20Constants.CLIENT_ID)
.map(String::valueOf).orElse(StringUtils.EMPTY);
val validRequest = OAuth20Utils.isResponseType(responseType, OAuth20ResponseTypes.DEVICE_CODE)
|| OAuth20Utils.isGrantType(grantType, OAuth20GrantTypes.DEVICE_CODE);
return validRequest && StringUtils.isNotBlank(clientId);
}
}
View on GitHub (pinned to e7288fc434)