apereo/cas · warning · UnauthorizedAuthenticationException
Adaptive authentication policy does not allow this request…
Error message
Adaptive authentication policy does not allow this request for [agent] and [geoLocation]
What it means
AbstractAuthenticationAction checks adaptive authentication policy (user-agent and geolocation) before granting an 'authenticate' event in the login webflow. When the policy rejects the request's device agent or geo location, it logs a warning and returns an 'error' event carrying an UnauthorizedAuthenticationException, driving the webflow to the authentication-failure transition.
Solutions
- Update cas.authn.adaptive.expected-user-agent or the adaptive policy config to allow the rejected agent/geo
- Remove or narrow the adaptive authentication policy that is blocking the request
- Check the CAS logs: the warn line names the exact agent and geoLocation values being denied
- If testing, set the request User-Agent to one matching the allowed pattern
Example fix
// before (application.properties) cas.authn.adaptive.expected-user-agent=^Mozilla.*Chrome$ // after cas.authn.adaptive.expected-user-agent=^Mozilla.*(Chrome|Firefox|Safari).*|CAS-Automation-Client
Defensive patterns
Strategy: validation
Validate before calling
// Before submitting login flow, check adaptive policy client-side
String userAgent = request.getHeader("User-Agent");
if (userAgent == null || !userAgent.matches(allowedAgentPattern)) {
// adapt or skip adaptive-protected flow
} Prevention
- Keep the adaptive user-agent regex in sync with all legitimate client agents including automation
- Log and review the warn output regularly to catch over-broad policies
- Test login with each supported browser/client after policy changes
- Provide fallback transitions for adaptive failures in the webflow
When it happens
Trigger: A login request whose User-Agent or GeoLocation from the request context fails the configured adaptive/expected-user-agent or risk/geo rules; the policy engine returns false so doExecuteInternal builds the failure event.
Common situations: Admins enabled cas.authn.adaptive policy for a user-agent regex or IP/geo range that unintentionally blocks legitimate browsers; clients behind new proxies present unlisted agents; testers run curl/automation agents not whitelisted; geolocation data missing or resolving to a disallowed country.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unable to locate authentication object in the webflow…
- Unable to determine authentication from the request context
- Provided token is not issued by and does not belong to
- Authentication chain is empty as no authentications have…
- Could not determine authentication from the request context
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/159146e5d6021e8c.
Report an issue: GitHub.
Appendix: source
Thrown at core/cas-server-core-webflow-api/src/main/java/org/apereo/cas/web/flow/actions/AbstractAuthenticationAction.java:46
@Slf4j
public abstract class AbstractAuthenticationAction extends BaseCasWebflowAction {
private final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver;
private final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver;
private final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy;
@Override
protected @Nullable Event doExecuteInternal(final RequestContext requestContext) throws Throwable {
if (!evaluateAdaptiveAuthenticationPolicy(requestContext)) {
val agent = WebUtils.getHttpServletRequestUserAgentFromRequestContext(requestContext);
val geoLocation = WebUtils.getHttpServletRequestGeoLocationFromRequestContext(requestContext);
val msg = "Adaptive authentication policy does not allow this request for " + agent + " and " + geoLocation;
LOGGER.warn(msg);
val map = CollectionUtils.<String, Throwable>wrap(UnauthorizedAuthenticationException.class.getSimpleName(),
new UnauthorizedAuthenticationException(msg));
val error = new AuthenticationException(msg, map, new HashMap<>());
val event = new Event(this, CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE,
new LocalAttributeMap<>(CasWebflowConstants.TRANSITION_ID_ERROR, error));
fireEventHooks(event, requestContext);
return event;
}
val serviceTicketEvent = serviceTicketRequestWebflowEventResolver.resolveSingle(requestContext);
if (serviceTicketEvent != null) {
fireEventHooks(serviceTicketEvent, requestContext);
return serviceTicketEvent;
}
val finalEvent = initialAuthenticationAttemptWebflowEventResolver.resolveSingle(requestContext);
fireEventHooks(finalEvent, requestContext);
return finalEvent;
}
View on GitHub (pinned to e7288fc434)