{"record":{"id":"3c213c7bd40f9c0f","repo":"apereo/cas","slug":"invalid-cookie-s-required-remote-address-s-does-3c213c","errorCode":null,"errorMessage":"Invalid cookie %s. Required remote address %s does not match %s","messagePattern":"Invalid cookie (.+?)\\. Required remote address (.+?) does not match (.+?)","errorType":"exception","errorClass":"InvalidCookieException","httpStatus":null,"severity":"warning","filePath":"core/cas-server-core-cookie-api/src/main/java/org/apereo/cas/web/support/mgmr/DefaultCasCookieValueManager.java","lineNumber":137,"sourceCode":"            throw new InvalidCookieException(message);\n        }\n\n        if (cookieProperties.isGeoLocateClientSession()) {\n            val clientLocationOrIp = getClientGeoLocation(clientInfo);\n            if (!cookieClientLocationOrIp.equals(clientLocationOrIp)) {\n                val message = \"Invalid cookie %s Required remote address %s does not match %s\"\n                    .formatted(cookieProperties.getName(), cookieClientLocationOrIp, clientLocationOrIp);\n                LOGGER.warn(message);\n                throw new InvalidCookieException(message);\n            }\n        } else {\n            val clientIpAddress = clientInfo.getClientIpAddress();\n            if (!cookieClientLocationOrIp.equals(clientIpAddress)) {\n                if (StringUtils.isBlank(cookieProperties.getAllowedIpAddressesPattern())\n                    || !RegexUtils.find(cookieProperties.getAllowedIpAddressesPattern(), clientIpAddress)) {\n                    val message = \"Invalid cookie %s. Required remote address %s does not match %s\"\n                        .formatted(cookieProperties.getName(), cookieClientLocationOrIp, clientIpAddress);\n                    LOGGER.warn(message);\n                    throw new InvalidCookieException(message);\n                }\n                LOGGER.debug(\"Required remote address [{}] does not match [{}], but it's authorized to proceed\",\n                    cookieClientLocationOrIp, clientIpAddress);\n            }\n        }\n\n        val agent = HttpRequestUtils.getHttpServletRequestUserAgent(request);\n        if (!cookieUserAgent.equals(agent)) {\n            val message = \"Invalid cookie %s. Required user-agent %s does not match %s\"\n                .formatted(cookieProperties.getName(), cookieUserAgent, agent);\n            LOGGER.warn(message);\n            throw new InvalidCookieException(message);\n        }\n        return cookieValue;\n    }\n}\n","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/core/cas-server-core-cookie-api/src/main/java/org/apereo/cas/web/support/mgmr/DefaultCasCookieValueManager.java#L119-L155","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Configure allowedIpAddressesPattern with a regex covering the client's legitimate IP ranges (e.g. '192\\\\.168\\\\..*')","Confirm X-Forwarded-For handling so the real client IP is resolved consistently","Ask affected users to clear cookies and re-login after network changes","If validation failures are unexpected attacks, keep the strict behavior and monitor logs"],"exampleFix":"// before\n// cas.tgc.pinnable-session-cookie.allowed-ip-addresses-pattern=\n// after: allow corporate egress ranges\n// cas.tgc.pinnable-session-cookie.allowed-ip-addresses-pattern=10\\\\..*|192\\\\.168\\\\..*","handlingStrategy":"validation","validationCode":"String currentIp = ClientInfoHolder.getClientInfo().getClientIpAddress();\nif (!cookieIp.equals(currentIp) && !RegexUtils.find(pattern, currentIp)) {\n    // will be rejected; clear cookie and re-auth\n}","typeGuard":"boolean ipAllowed(String cookieIp, String currentIp, String pattern) {\n    return cookieIp.equals(currentIp) || RegexUtils.find(pattern, currentIp);\n}","tryCatchPattern":"try { obtainCookieValue(...); } catch (InvalidCookieException e) {\n    redirectToLogin(); // IP changed beyond allowed pattern\n}","preventionTips":["Set allowedIpAddressesPattern when clients sit behind rotating egress IPs","Test patterns against both IPv4 and IPv6 forms","Treat repeated mismatches as possible cookie replay and alert"],"tags":["cookie","ip-binding","security","invalid-cookie"],"backgroundTag":"client-ip-mismatch","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}