{"record":{"id":"ecd8852d34a6fe00","repo":"apereo/cas","slug":"invalid-cookie-name-required-user-agent-cookie","errorCode":null,"errorMessage":"Invalid cookie <name>. Required user-agent <cookieAgent> does not match <agent>","messagePattern":"Invalid cookie <name>\\. Required user-agent <cookieAgent> does not match <agent>","errorType":"exception","errorClass":"InvalidCookieException","httpStatus":null,"severity":"error","filePath":"core/cas-server-core-cookie-api/src/main/java/org/apereo/cas/web/support/mgmr/DefaultCasCookieValueManager.java","lineNumber":150,"sourceCode":"            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":132,"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#L132-L155","documentation":"CAS validates that the User-Agent header presented when reading a compound cookie matches the User-Agent that was captured when the cookie was created. The cookie value embeds the original agent string; if the incoming request's agent differs, the cookie is presumed stolen or replayed from another client and InvalidCookieException is thrown to reject it.","triggerScenarios":"Calling obtainValueFromCompoundCookie (via CasCookieValueManager.obtainCookieValue) when the request's User-Agent header does not exactly equal the agent string stored in the compound cookie — e.g. the client upgraded its browser, rotated behind different proxies that rewrite User-Agent, the header is missing/null, or the cookie was copied to another device.","commonSituations":"Reverse proxies or CDNs (Cloudflare, ModSecurity) stripping or normalizing User-Agent; browser auto-updates mid-session; load balancers spreading requests across clients with different agents; API clients forgetting to send the same User-Agent on every call; cookies shared between curl and a browser.","solutions":["Ensure the client sends the exact same User-Agent header on every request that carries the CAS cookie (pin it in API clients, e.g. curl -A).","Check intermediaries (proxies, WAFs, CDNs) for rules that rewrite or strip the User-Agent header and disable them for CAS routes.","Investigate why the agent differs between cookie creation and use — log both values; if the cookie was legitimately moved between devices, force re-authentication instead.","If agent binding is too strict for your environment, reduce cookie security by lowering the cookie security policy (e.g. disable user-agent binding in cas.cookie.* properties / getCookie().setBrowsers()), accepting the weaker security.","Clear the stale cookie and re-authenticate to mint a fresh one bound to the current agent."],"exampleFix":"// before: client sends differing agents per request\ncurl -H 'User-Agent: curl/8.0' https://cas/cas/v1/tickets -d '...'\ncurl https://cas/cas/... -b TGC=...   # no User-Agent -> mismatch\n// after: pin the same agent everywhere\ncurl -H 'User-Agent: MyApp/1.0' https://cas/cas/v1/tickets -d '...'\ncurl -H 'User-Agent: MyApp/1.0' https://cas/cas/... -b TGC=...","handlingStrategy":"try-catch","validationCode":"String ua = HttpRequestUtils.getHttpServletRequestUserAgent(request);\nString expected = /* agent stored when cookie was issued */;\nif (ua == null || !ua.equals(expected)) {\n    // skip obtainCookieValue / force re-auth\n}","typeGuard":null,"tryCatchPattern":"try {\n    String value = cookieValueManager.obtainCookieValue(cookie, request);\n} catch (InvalidCookieException e) {\n    // clear cookie and redirect to login\n}","preventionTips":["Send a fixed, non-empty User-Agent header from all non-browser clients.","Audit proxies/WAFs for User-Agent rewriting on CAS routes.","Avoid copying session cookies between devices or browsers.","Keep browser auto-update behavior in mind; user-agent binding makes sessions agent-version-bound by design."],"tags":["cookie","user-agent","security","session"],"backgroundTag":"invalid-cookie-exception","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"}