{"record":{"id":"159146e5d6021e8c","repo":"apereo/cas","slug":"adaptive-authentication-policy-does-not-allow-this","errorCode":null,"errorMessage":"Adaptive authentication policy does not allow this request for [agent] and [geoLocation]","messagePattern":"Adaptive authentication policy does not allow this request for \\[agent\\] and \\[geoLocation\\]","errorType":"exception","errorClass":"UnauthorizedAuthenticationException","httpStatus":null,"severity":"warning","filePath":"core/cas-server-core-webflow-api/src/main/java/org/apereo/cas/web/flow/actions/AbstractAuthenticationAction.java","lineNumber":46,"sourceCode":"@Slf4j\npublic abstract class AbstractAuthenticationAction extends BaseCasWebflowAction {\n\n    private final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver;\n\n    private final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver;\n\n    private final AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy;\n\n    @Override\n    protected @Nullable Event doExecuteInternal(final RequestContext requestContext) throws Throwable {\n        if (!evaluateAdaptiveAuthenticationPolicy(requestContext)) {\n            val agent = WebUtils.getHttpServletRequestUserAgentFromRequestContext(requestContext);\n            val geoLocation = WebUtils.getHttpServletRequestGeoLocationFromRequestContext(requestContext);\n\n            val msg = \"Adaptive authentication policy does not allow this request for \" + agent + \" and \" + geoLocation;\n            LOGGER.warn(msg);\n            val map = CollectionUtils.<String, Throwable>wrap(UnauthorizedAuthenticationException.class.getSimpleName(),\n                new UnauthorizedAuthenticationException(msg));\n            val error = new AuthenticationException(msg, map, new HashMap<>());\n            val event = new Event(this, CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE,\n                new LocalAttributeMap<>(CasWebflowConstants.TRANSITION_ID_ERROR, error));\n            fireEventHooks(event, requestContext);\n            return event;\n        }\n\n        val serviceTicketEvent = serviceTicketRequestWebflowEventResolver.resolveSingle(requestContext);\n        if (serviceTicketEvent != null) {\n            fireEventHooks(serviceTicketEvent, requestContext);\n            return serviceTicketEvent;\n        }\n\n        val finalEvent = initialAuthenticationAttemptWebflowEventResolver.resolveSingle(requestContext);\n        fireEventHooks(finalEvent, requestContext);\n        return finalEvent;\n    }\n","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/core/cas-server-core-webflow-api/src/main/java/org/apereo/cas/web/flow/actions/AbstractAuthenticationAction.java#L28-L64","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (application.properties)\ncas.authn.adaptive.expected-user-agent=^Mozilla.*Chrome$\n// after\ncas.authn.adaptive.expected-user-agent=^Mozilla.*(Chrome|Firefox|Safari).*|CAS-Automation-Client","handlingStrategy":"validation","validationCode":"// Before submitting login flow, check adaptive policy client-side\nString userAgent = request.getHeader(\"User-Agent\");\nif (userAgent == null || !userAgent.matches(allowedAgentPattern)) {\n    // adapt or skip adaptive-protected flow\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["authentication","adaptive-policy","webflow"],"backgroundTag":"insufficient-permissions","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"}