{"record":{"id":"c2c65392fc6bb82e","repo":"apereo/cas","slug":"request-does-not-specify-a-user-agent","errorCode":null,"errorMessage":"Request does not specify a user-agent","messagePattern":"Request does not specify a user-agent","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/cas-server-core-cookie-api/src/main/java/org/apereo/cas/web/support/mgmr/DefaultCasCookieValueManager.java","lineNumber":69,"sourceCode":"        this.geoLocationService = geoLocationService;\n        this.cookieProperties = cookieProperties;\n    }\n\n    @Override\n    protected String buildCompoundCookieValue(final String givenCookieValue, final HttpServletRequest request) {\n        val builder = new StringBuilder(givenCookieValue);\n\n        if (cookieProperties.isPinToSession()) {\n            val clientInfo = ClientInfoHolder.getClientInfo();\n            if (clientInfo != null) {\n                val clientLocation = cookieProperties.isGeoLocateClientSession()\n                    ? getClientGeoLocation(clientInfo)\n                    : clientInfo.getClientIpAddress();\n                builder.append(COOKIE_FIELD_SEPARATOR).append(clientLocation);\n            }\n            val userAgent = HttpRequestUtils.getHttpServletRequestUserAgent(request);\n            if (StringUtils.isBlank(userAgent)) {\n                throw new IllegalStateException(\"Request does not specify a user-agent\");\n            }\n            builder.append(COOKIE_FIELD_SEPARATOR).append(userAgent);\n        } else {\n            LOGGER.trace(\"Cookie session-pinning is disabled\");\n        }\n\n        return builder.toString();\n    }\n\n    private String getClientGeoLocation(final ClientInfo clientInfo) {\n        return geoLocationService\n            .stream()\n            .map(service -> {\n                val geoLocation = service.locate(clientInfo.getClientIpAddress());\n                if (geoLocation != null && geoLocation.getAddresses() != null && !geoLocation.getAddresses().isEmpty()) {\n                    return org.springframework.util.StringUtils.collectionToCommaDelimitedString(geoLocation.getAddresses());\n                }\n                return clientInfo.getClientIpAddress();","sourceCodeStart":51,"sourceCodeEnd":87,"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#L51-L87","documentation":"DefaultCasCookieValueManager.buildCompoundCookieValue builds a pinned cookie value combining principal, IP/geo location, and the request's User-Agent when cookie session pinning is enabled. If HttpRequestUtils.getHttpServletRequestUserAgent(request) yields a blank user agent, it throws IllegalStateException because the pinned value could never be verified on later requests.","triggerScenarios":"Calling buildCompoundCookieValue (via buildValue when encrypt/decrypt + pinning are enabled, e.g. for the TGC) with an HttpServletRequest that has no User-Agent header while cas.tgc.pin-to-user-agent (or similar pinning flag) is true.","commonSituations":"API/non-browser clients, health checks, or curl scripts calling CAS login endpoints without a User-Agent header; corporate proxies or WAFs stripping the header; load tests / http client defaults omitting the header; container probes hitting authenticated endpoints.","solutions":["Ensure clients always send a User-Agent header (set one in curl/http clients, e.g. curl -A 'MyAgent/1.0').","Check intermediary proxies/WAFs and re-add the User-Agent header if stripped.","If the client is a non-browser integration, disable session pinning (e.g. cas.tgc.pin-to-user-agent=false).","Exclude health-check/probe paths from cookie-based authenticated flows."],"exampleFix":"// before\ncurl -X POST https://cas.example.org/cas/login -d username=u -d password=p\n// after\ncurl -A \"svc-client/1.0\" -X POST https://cas.example.org/cas/login -d username=u -d password=p","handlingStrategy":"validation","validationCode":"if (HttpRequestUtils.getHttpServletRequestUserAgent(request) == null) {\n  // do not call buildCompoundCookieValue with pinning enabled\n}","typeGuard":null,"tryCatchPattern":"try {\n  val value = cookieManager.buildCompoundCookieValue(...);\n} catch (IllegalStateException e) {\n  LOGGER.warn(\"Missing user-agent for pinned cookie\", e);\n}","preventionTips":["Always send User-Agent from scripts, integrations and health probes","Verify proxies/WAFs do not strip User-Agent","Disable pin-to-user-agent for API-only integrations"],"tags":["cookie","http-headers","user-agent"],"backgroundTag":"missing-required-argument","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"}