apereo/cas · warning

User agent [ ] is rejected for authentication

Error message

User agent [{}] is rejected for authentication

What it means

DefaultAdaptiveAuthenticationPolicy rejects the authentication request when the User-Agent string matches the rejected user-agent patterns configured under cas.authn.adaptive.policy.reject-browsers. The warning logs the rejected agent string.

Solutions

  1. Adjust cas.authn.adaptive.policy.reject-browsers patterns to stop matching the legitimate agent.
  2. Whitelist the affected client's User-Agent or use a narrower, more specific regex.
  3. Identify the offending client from the logged agent string and update your bot/monitoring to send a compliant header.
  4. Review patterns after browser version upgrades to prevent accidental matches.

Example fix

// before
cas.authn.adaptive.policy.reject-browsers=.*Firefox.*
// after: narrow to legacy Firefox only
cas.authn.adaptive.policy.reject-browsers=Firefox/([0-9]|[1-9][0-9])\.
Defensive patterns

Strategy: validation

Validate before calling

val patterns = adaptiveProps.getPolicy().getRejectBrowsers();
val ua = request.getHeader("User-Agent");
if (patterns.stream().anyMatch(p -> ua.matches(p))) {
    LOGGER.warn("User agent {} will be rejected by adaptive policy", ua);
}

Prevention

When it happens

Trigger: isUserAgentRejected(userAgent) matches the request's User-Agent header against the configured browser/agent patterns after IP checks pass.

Common situations: Aggressive bots/scripts hitting the login endpoint; browsers sending unusual User-Agent strings caught by over-broad regex; new browser versions matching stale patterns; API clients lacking a conventional User-Agent.

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


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/6f7ba42ae584b8aa. Report an issue: GitHub.

Appendix: source

Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/adaptive/DefaultAdaptiveAuthenticationPolicy.java:48

    private final AdaptiveAuthenticationProperties adaptiveAuthenticationProperties;

    @Override
    public boolean isAuthenticationRequestAllowed(final RequestContext requestContext, final String userAgent,
                                                  final GeoLocationRequest location) throws Throwable {
        val clientInfo = ClientInfoHolder.getClientInfo();
        if (clientInfo == null || StringUtils.isBlank(userAgent)) {
            LOGGER.warn("No client IP or user-agent was provided. Skipping adaptive authentication policy...");
            return true;
        }
        val clientIp = clientInfo.getClientIpAddress();
        if (isIpAddressRejected(requestContext, clientIp)) {
            LOGGER.warn("Client IP [{}] is rejected for authentication", clientIp);
            return false;
        }

        if (isUserAgentRejected(userAgent)) {
            LOGGER.warn("User agent [{}] is rejected for authentication", userAgent);
            return false;
        }
        LOGGER.debug("User agent [{}] is authorized to proceed", userAgent);
        if (this.geoLocationService != null && location != null && StringUtils.isNotBlank(clientIp)
            && StringUtils.isNotBlank(this.adaptiveAuthenticationProperties.getPolicy().getRejectCountries())) {
            val loc = this.geoLocationService.locate(clientIp, location);
            if (loc != null) {
                LOGGER.debug("Determined geolocation for [{}] to be [{}]", clientIp, loc);
                if (isGeoLocationCountryRejected(loc)) {
                    LOGGER.warn("Client [{}] is rejected for authentication based on country location", clientIp);
                    return false;
                }
            } else {
                LOGGER.info("Could not determine geolocation for [{}]", clientIp);
            }
        }
        LOGGER.debug("Adaptive authentication policy has authorized client [{}] to proceed.", clientIp);
        return true;

View on GitHub (pinned to e7288fc434)