apereo/cas · warning · InvalidCookieException

Invalid cookie . Required user-agent does not match

Error message

Invalid cookie %s. Required user-agent %s does not match %s

What it means

CAS binds compound cookies to the browser's User-Agent at creation time. During validation, the current request's User-Agent (via HttpRequestUtils.getHttpServletRequestUserAgent) is compared to the stored one; any mismatch rejects the cookie as InvalidCookieException. This mitigates cookie theft to a different client environment.

Solutions

  1. Disable user-agent binding for the cookie (set the relevant user-agent-check property to false) if UA volatility is causing logouts
  2. Ensure proxies forward the User-Agent header unchanged
  3. Re-authenticate after browser upgrades (expected behavior)
  4. Use consistent clients for automated tests, or copy the same UA header

Example fix

// before: proxy strips header
// proxy_set_header User-Agent "";
// after: forward it
// proxy_set_header User-Agent $http_user_agent;
Defensive patterns

Strategy: validation

Validate before calling

String agent = HttpRequestUtils.getHttpServletRequestUserAgent(request);
String storedAgent = /* part 3 of compound cookie */;
if (!storedAgent.equals(agent)) { /* cookie will be rejected */ }

Type guard

boolean userAgentMatches(String stored, HttpServletRequest req) {
    return Objects.equals(stored, HttpRequestUtils.getHttpServletRequestUserAgent(req));
}

Try / catch

try { obtainCookieValue(...); } catch (InvalidCookieException e) {
    // UA changed (browser update/proxy strip); force re-auth
    redirectToLogin();
}

Prevention

When it happens

Trigger: cookieUserAgent != agent — user upgraded/switched browser mid-session, browser auto-update changed the UA string, CAS is behind a proxy that strips/normalizes the User-Agent header, or the request path receives requests from a non-browser client (curl, health check) carrying the cookie.

Common situations: Browser major-version auto-update invalidates sessions (UA includes version); monitoring scripts replaying cookies; reverse proxy removing User-Agent so agent resolves to null/blank; mobile apps changing UA between app versions.

Related errors


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

Appendix: source

Thrown at core/cas-server-core-cookie-api/src/main/java/org/apereo/cas/web/support/mgmr/DefaultCasCookieValueManager.java:149

            val clientIpAddress = clientInfo.getClientIpAddress();
            if (!cookieClientLocationOrIp.equals(clientIpAddress)) {
                if (StringUtils.isBlank(cookieProperties.getAllowedIpAddressesPattern())
                    || !RegexUtils.find(cookieProperties.getAllowedIpAddressesPattern(), clientIpAddress)) {
                    val message = "Invalid cookie %s. Required remote address %s does not match %s"
                        .formatted(cookieProperties.getName(), cookieClientLocationOrIp, clientIpAddress);
                    LOGGER.warn(message);
                    throw new InvalidCookieException(message);
                }
                LOGGER.debug("Required remote address [{}] does not match [{}], but it's authorized to proceed",
                    cookieClientLocationOrIp, clientIpAddress);
            }
        }

        val agent = HttpRequestUtils.getHttpServletRequestUserAgent(request);
        if (!cookieUserAgent.equals(agent)) {
            val message = "Invalid cookie %s. Required user-agent %s does not match %s"
                .formatted(cookieProperties.getName(), cookieUserAgent, agent);
            LOGGER.warn(message);
            throw new InvalidCookieException(message);
        }
        return cookieValue;
    }
}

View on GitHub (pinned to e7288fc434)