apereo/cas · error · InvalidCookieException

Invalid cookie Required remote address does not match

Error message

Invalid cookie <name> Required remote address <cookieIp> does not match <clientLocation>

What it means

Session pinning with geo-location enabled: the geo-location (or IP) stored in the cookie does not equal the geo-location resolved for the current request's client. The cookie is rejected because the client's apparent location changed since the cookie was issued, which is treated as possible theft/replay of the cookie.

Solutions

  1. Re-authenticate to obtain a fresh cookie from the current location
  2. Verify geo-location resolution is consistent/stable; flaky geolocation data causes false positives
  3. Disable geoLocateClientSession if client roaming is expected and acceptable
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at core/cas-server-core-cookie-api/src/main/java/org/apereo/cas/web/support/mgmr/DefaultCasCookieValueManager.java:128 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/520b495ed789c66d. 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:128

        if (Stream.of(cookieValue, cookieClientLocationOrIp, cookieUserAgent).anyMatch(StringUtils::isBlank)) {
            throw new InvalidCookieException("Invalid cookie %s. Required fields are empty".formatted(cookieProperties.getName()));
        }

        val clientInfo = ClientInfoHolder.getClientInfo();
        if (clientInfo == null) {
            val message = "Unable to match required remote address %s because client ip at time of cookie creation is unknown for cookie %s"
                .formatted(cookieProperties.getName(), cookieClientLocationOrIp);
            LOGGER.warn(message);
            throw new InvalidCookieException(message);
        }

        if (cookieProperties.isGeoLocateClientSession()) {
            val clientLocationOrIp = getClientGeoLocation(clientInfo);
            if (!cookieClientLocationOrIp.equals(clientLocationOrIp)) {
                val message = "Invalid cookie %s Required remote address %s does not match %s"
                    .formatted(cookieProperties.getName(), cookieClientLocationOrIp, clientLocationOrIp);
                LOGGER.warn(message);
                throw new InvalidCookieException(message);
            }
        } else {
            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)) {

View on GitHub (pinned to e7288fc434)