{"record":{"id":"b133987d82c9365e","repo":"apereo/cas","slug":"invalid-cookie-s-required-user-agent-s-does-not","errorCode":null,"errorMessage":"Invalid cookie %s. Required user-agent %s does not match %s","messagePattern":"Invalid cookie (.+?)\\. Required user-agent (.+?) 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":149,"sourceCode":"            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":131,"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#L131-L155","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Disable user-agent binding for the cookie (set the relevant user-agent-check property to false) if UA volatility is causing logouts","Ensure proxies forward the User-Agent header unchanged","Re-authenticate after browser upgrades (expected behavior)","Use consistent clients for automated tests, or copy the same UA header"],"exampleFix":"// before: proxy strips header\n// proxy_set_header User-Agent \"\";\n// after: forward it\n// proxy_set_header User-Agent $http_user_agent;","handlingStrategy":"validation","validationCode":"String agent = HttpRequestUtils.getHttpServletRequestUserAgent(request);\nString storedAgent = /* part 3 of compound cookie */;\nif (!storedAgent.equals(agent)) { /* cookie will be rejected */ }","typeGuard":"boolean userAgentMatches(String stored, HttpServletRequest req) {\n    return Objects.equals(stored, HttpRequestUtils.getHttpServletRequestUserAgent(req));\n}","tryCatchPattern":"try { obtainCookieValue(...); } catch (InvalidCookieException e) {\n    // UA changed (browser update/proxy strip); force re-auth\n    redirectToLogin();\n}","preventionTips":["Disable user-agent binding if auto-updates cause mass logouts","Ensure reverse proxies forward User-Agent unchanged","Use stable UA strings in automated tests"],"tags":["cookie","user-agent","security"],"backgroundTag":"user-agent-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"}