apereo/cas · warning · InvalidCookieException

Invalid cookie . Required remote address does not match

Error message

Invalid cookie %s. Required remote address %s does not match %s

What it means

When geolocation binding is disabled, CAS compares the IP stored in the cookie against the current request's client IP. If they differ and the new IP does not match the configured allowedIpAddressesPattern regex, InvalidCookieException is thrown. The pattern acts as an escape hatch for clients whose IPs legitimately change within known ranges.

Solutions

  1. Configure allowedIpAddressesPattern with a regex covering the client's legitimate IP ranges (e.g. '192\\.168\\..*')
  2. Confirm X-Forwarded-For handling so the real client IP is resolved consistently
  3. Ask affected users to clear cookies and re-login after network changes
  4. If validation failures are unexpected attacks, keep the strict behavior and monitor logs

Example fix

// before
// cas.tgc.pinnable-session-cookie.allowed-ip-addresses-pattern=
// after: allow corporate egress ranges
// cas.tgc.pinnable-session-cookie.allowed-ip-addresses-pattern=10\\..*|192\\.168\\..*
Defensive patterns

Strategy: validation

Validate before calling

String currentIp = ClientInfoHolder.getClientInfo().getClientIpAddress();
if (!cookieIp.equals(currentIp) && !RegexUtils.find(pattern, currentIp)) {
    // will be rejected; clear cookie and re-auth
}

Type guard

boolean ipAllowed(String cookieIp, String currentIp, String pattern) {
    return cookieIp.equals(currentIp) || RegexUtils.find(pattern, currentIp);
}

Try / catch

try { obtainCookieValue(...); } catch (InvalidCookieException e) {
    redirectToLogin(); // IP changed beyond allowed pattern
}

Prevention

When it happens

Trigger: cookieClientLocationOrIp != clientInfo.getClientIpAddress() AND (allowedIpAddressesPattern is blank OR RegexUtils.find(pattern, currentIp) is false) — e.g. client switched networks, load balancer presents different egress IP, or allowedIpAddressesPattern not configured despite NAT/proxy IP rotation.

Common situations: Users behind rotating corporate proxies fail validation; admin forgot to set cas.tgc allowed-ip-addresses-pattern; IPv4 cookie vs IPv6 current address comparison mismatch; cookie replayed from a different machine (this error is the intended protection working).

Related errors


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

            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)) {
            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)