apereo/cas · error
Interrupt response has blocked the authentication flow
Error message
Interrupt response has blocked the authentication flow
What it means
FinalizeInterruptFlowAction checks the interrupt response's execute behavior; when the user was instructed to acknowledge/blocked and the flow must not continue, CAS logs 'Interrupt response has blocked the authentication flow' and throws UnauthorizedServiceException.denied("Rejected"), aborting the webflow. This is the enforcement point of CAS's interrupt (notification/forced-action) feature.
Solutions
- Have the user accept the required interrupt message/options on the interrupt screen
- Review the service's interrupt policy (WebflowInterruptAttribute/registered service interrupt settings) if blocking is unintended
- Check the interrupt response stored for the user and remove stale blocked responses if the policy has changed
- Disable the interrupt feature for the service if it should not be enforced
Example fix
// before (service registered with mandatory interrupt the user never accepted) "interrupt": true // after (interrupt satisfied via accepted response or disabled) "interrupt": false
Defensive patterns
Strategy: fallback
Validate before calling
// check the user's interrupt response state before entering the flow
val response = interruptInformer.findInterruptResponse(authentication, service);
if (response != null && response.isBlocked()) {
// do not attempt login; route user to acknowledgment screen
} Try / catch
try { flowExecutor.execute(...); } catch (UnauthorizedServiceException e) { LOGGER.info("Interrupt blocked flow for user"); redirectToInterruptScreen(); } Prevention
- Inform users they must accept interrupt messages to proceed
- Keep interrupt messages simple and mandatory-only where possible
- Review registered service interrupt policies before enabling
- Catch UnauthorizedServiceException in protocol adapters to return clean errors
When it happens
Trigger: A user finishes the interrupt screen with a response whose policy blocks continuation (e.g. required terms not accepted, mandatory notification not acknowledged, or a block URL configured — in the shown source an external redirect to accessUrl occurs for a block URL; otherwise the warn/exception path fires).
Common situations: Admins enabling forced interrupt messages (usage policy, terms of use) that users must accept; service access denied until the user completes the required interrupt action.
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Link [ ] is not valid and is not part of the interrupt…
- State [ : : ] does not have a matching transition for
- Deserialization error
- Unable to locate authentication object in the webflow…
- UNAUTHORIZED_SERVICE_PROXY
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/a1db1eb64266557d.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-interrupt-webflow/src/main/java/org/apereo/cas/interrupt/webflow/actions/FinalizeInterruptFlowAction.java:43
public class FinalizeInterruptFlowAction extends BaseCasWebflowAction {
private final InterruptTrackingEngine interruptTrackingEngine;
@Override
protected @Nullable Event doExecuteInternal(final RequestContext requestContext) throws Throwable {
val response = InterruptUtils.getInterruptFrom(requestContext);
if (response.isBlock() && !requestContext.getRequestParameters().contains("link")) {
val registeredService = WebUtils.getRegisteredService(requestContext);
val accessUrl = Optional.ofNullable(registeredService)
.map(service -> service.getAccessStrategy().getUnauthorizedRedirectUrl())
.orElse(null);
if (accessUrl != null) {
val url = accessUrl.toURL().toExternalForm();
val externalContext = requestContext.getExternalContext();
externalContext.requestExternalRedirect(url);
externalContext.recordResponseComplete();
return eventFactory.event(this, CasWebflowConstants.TRANSITION_ID_STOP);
}
LOGGER.warn("Interrupt response has blocked the authentication flow");
throw UnauthorizedServiceException.denied("Rejected");
}
if (requestContext.getRequestParameters().contains("link")) {
val link = requestContext.getRequestParameters().get("link");
LOGGER.debug("Finalizing interrupt flow with link [{}]", link);
val validLink = response.getLinks().containsValue(link);
if (!validLink) {
LOGGER.warn("Link [{}] is not valid and is not part of the interrupt response", link);
throw UnauthorizedServiceException.denied("Rejected");
}
}
val authentication = WebUtils.getAuthentication(requestContext);
interruptTrackingEngine.trackInterrupt(requestContext, response);
WebUtils.putAuthentication(authentication, requestContext);
WebUtils.putInterruptAuthenticationFlowFinalized(requestContext);
return success();View on GitHub (pinned to e7288fc434)