@Override
    protected String buildCompoundCookieValue(final String givenCookieValue, final HttpServletRequest request) {
        val builder = new StringBuilder(givenCookieValue);

        if (cookieProperties.isPinToSession()) {
            val clientInfo = ClientInfoHolder.getClientInfo();
            if (clientInfo != null) {
                val clientLocation = cookieProperties.isGeoLocateClientSession()
                    ? getClientGeoLocation(clientInfo)
                    : clientInfo.getClientIpAddress();
                builder.append(COOKIE_FIELD_SEPARATOR).append(clientLocation);
            }
            val userAgent = HttpRequestUtils.getHttpServletRequestUserAgent(request);
            if (StringUtils.isBlank(userAgent)) {
                throw new IllegalStateException("Request does not specify a user-agent");
            }
            builder.append(COOKIE_FIELD_SEPARATOR).append(userAgent);
        } else {
            LOGGER.trace("Cookie session-pinning is disabled");
        }

        return builder.toString();
    }
The {@link DefaultCasCookieValueManager} is responsible for creating
the CAS SSO cookie and encrypting and signing its value.
<p>
This class by default ({@code CookieProperties.isPinToSession=true}) ensures the cookie is used on a
request from same IP and with the same user-agent as when cookie was created.
The client info (with original client ip) may be null if cluster failover occurs and session replication not working.

@author Misagh Moayyed
@since 4.1
core/cas-server-core-cookie-api/src/main/java/org/apereo/cas/web/support/mgmr/DefaultCasCookieValueManager.java