apereo/cas · error · InvalidCookieException

Unable to match required address

Error message

Unable to match required address <ip> because client ip at time of cookie creation is unknown for cookie <name>

What it means

The cookie was pinned to the client's IP (or geo-location) at creation time, but ClientInfoHolder.getClientInfo() returned null for the current request, so there is no client IP to compare against the address stored in the cookie. Session-pinning validation cannot proceed, and the cookie is rejected rather than trusted blindly — a defensive check against replay from an unverifiable context.

Solutions

  1. Ensure the request flows through the CAS webflow/servlet pipeline so ClientInfoHolder is populated
  2. Check that any filter which sets ClientInfo (e.g., ClientInfoThreadLocalFilter) runs before cookie validation
  3. If session pinning cannot be supported for this path, disable pinToSession for the cookie
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:119 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/6a4b0ebf9ceaf050. 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:119

            return cookieValue;
        }

        if (cookieParts.size() != COOKIE_FIELDS_LENGTH) {
            throw new InvalidCookieException("Invalid cookie %s. Required fields are missing".formatted(cookieProperties.getName()));
        }
        val cookieClientLocationOrIp = cookieParts.get(1);
        val cookieUserAgent = cookieParts.get(2);

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

View on GitHub (pinned to e7288fc434)