{"record":{"id":"69039bd593824042","repo":"apereo/cas","slug":"no-state-could-be-found-to-determine-session-state","errorCode":null,"errorMessage":"No state could be found to determine session state","messagePattern":"No state could be found to determine session state","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-wsfederation/src/main/java/org/apereo/cas/support/wsfederation/web/WsFederationCookieManager.java","lineNumber":70,"sourceCode":"            throw new IllegalArgumentException(\"No \" + WCTX + \" parameter is found\");\n        }\n\n        val configuration = configurations.stream()\n            .filter(cookie -> cookie.getId().equalsIgnoreCase(contextId))\n            .findFirst()\n            .orElseThrow(() -> new IllegalArgumentException(\"Could not locate WsFederation configuration for \" + contextId));\n\n        val cookieGen = configuration.getCookieGenerator();\n        var serverState = cookieGen.retrieveCookieValue(request);\n        if (StringUtils.isBlank(serverState)) {\n            serverState = Optional.ofNullable(request.getSession(false))\n                .map(session -> session.getAttribute(configuration.getId()))\n                .map(String.class::cast)\n                .orElse(null);\n        }\n        if (StringUtils.isBlank(serverState)) {\n            LOGGER.error(\"No server state value could be retrieved to determine the state of the delegated authentication session\");\n            throw new IllegalArgumentException(\"No state could be found to determine session state\");\n        }\n        val blob = EncodingUtils.hexDecode(serverState);\n        val session = serializer.from(blob);\n        request.setAttribute(casProperties.getTheme().getParamName(), session.get(casProperties.getTheme().getParamName()));\n        request.setAttribute(casProperties.getLocale().getParamName(), session.get(casProperties.getLocale().getParamName()));\n        request.setAttribute(CasProtocolConstants.PARAMETER_METHOD, session.get(CasProtocolConstants.PARAMETER_METHOD));\n\n        val serviceKey = CasProtocolConstants.PARAMETER_SERVICE + '-' + contextId;\n        val service = (Service) session.get(serviceKey);\n        LOGGER.debug(\"Located service [{}] from session\", service);\n        WebUtils.putServiceIntoFlowScope(context, service);\n        return service;\n    }\n\n    /**\n     * Store.\n     *\n     * @param request       the request","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-wsfederation/src/main/java/org/apereo/cas/support/wsfederation/web/WsFederationCookieManager.java#L52-L88","documentation":"WsFederationCookieManager.retrieve() reconstructs the delegated-authentication session state from a serialized 'serverState' value taken from the request session (keyed by the identity-provider configuration id). If no non-blank state value can be found, CAS cannot correlate the callback with an in-flight WS-Federation sign-in and throws IllegalArgumentException to abort the flow.","triggerScenarios":"retrieve() is invoked during WS-Federation callback handling but neither the session attribute named configuration.getId() nor the state cookie yields a non-blank string — e.g. the user hits the callback URL directly, the HTTP session expired during the IdP redirect, or cookies were dropped.","commonSituations":"Browsers blocking cookies (SameSite/third-party), load-balanced CAS without sticky sessions, session timeout between /login redirect and ADFS callback, users bookmarking or replaying callback URLs, or a changed configuration id making the state key unresolvable.","solutions":["Ensure the CAS session cookie survives the full WS-Federation round trip (SameSite settings, no cookie stripping, sticky sessions on the load balancer).","Restart the delegated sign-in from the initial /login redirect instead of invoking the callback URL directly.","Verify the WsFederation identity-provider configuration id is stable across nodes and restarts, since it names the state attribute/cookie.","Increase session timeout or persist state out-of-session if IdP redirects are slow."],"exampleFix":"// before\nString serverState = cookieManager.retrieve(request);\n// after\ntry {\n    String serverState = cookieManager.retrieve(request);\n} catch (IllegalArgumentException e) {\n    LOGGER.warn(\"WS-Fed state missing; restarting delegated authentication\", e);\n    response.sendRedirect(loginUrl);\n}","handlingStrategy":"try-catch","validationCode":"HttpSession s = request.getSession(false);\nObject st = (s != null) ? s.getAttribute(config.getId()) : null;\nif (!(st instanceof String) || ((String) st).isBlank()) { /* restart delegated auth before calling retrieve */ }","typeGuard":"boolean hasServerState(HttpServletRequest req, WsFederationIdentityProviderConfiguration cfg) {\n    HttpSession s = req.getSession(false);\n    return s != null && s.getAttribute(cfg.getId()) instanceof String st && !st.isBlank();\n}","tryCatchPattern":"try {\n    cookieManager.retrieve(request);\n} catch (IllegalArgumentException e) {\n    // missing/blank WS-Fed state: restart the delegated sign-in redirect\n}","preventionTips":["Always enter the flow via /login; never call the callback URL out of band.","Ensure session cookies survive the IdP redirect (SameSite, sticky sessions).","Monitor session timeouts versus slow IdP round trips.","Keep the identity-provider configuration id stable across nodes."],"tags":["ws-federation","sso","cookie","delegated-authentication"],"backgroundTag":"session-state-lost","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"}