apereo/cas · error · UnauthorizedAuthenticationException

Unable to determine the [WA] parameter

Error message

Unable to determine the [WA] parameter

What it means

WS-Federation requests must carry a `wa` (requested action) query parameter such as wsignin1.0 or wsignout1.0. WSFederationValidateRequestController.handleFederationRequest parses the request and throws UnauthorizedAuthenticationException when `wa` is blank, since it cannot dispatch to sign-in or sign-out handling without an action.

Solutions

  1. Ensure the relying party includes `wa=wsignin1.0` (or `wa=wsignout1.0` / `wsignoutcleanup1.0`) in the URL/POST to the CAS WS-Federation endpoint.
  2. Verify the full WS-Fed parameter set (wa, wtrealm, wctx, wreply) is present and that any proxy in front of CAS preserves the query string or form body.
  3. Test with a canonical URL like /cas/ws-idp/federation?wa=wsignin1.0&wtrealm=<realm>&wreply=<url> to confirm the endpoint itself is fine.
  4. If your RP framework omits `wa` on sign-out cleanup requests, configure it to send wsignoutcleanup1.0 explicitly.

Example fix

// before (RP-generated redirect, missing wa)
response.sendRedirect("https://cas.example.org/cas/ws-idp/federation?wtrealm=myRealm");
// after
response.sendRedirect("https://cas.example.org/cas/ws-idp/federation?wa=wsignin1.0&wtrealm=myRealm&wreply=https%3A%2F%2Fapp.example.org%2Fcallback");
Defensive patterns

Strategy: validation

Validate before calling

// Before redirecting to the CAS WS-Fed endpoint from an RP:
if (!request.getParameterMap().containsKey("wa") || request.getParameter("wa").isBlank()) {
    throw new IllegalArgumentException("wa parameter is required (e.g. wsignin1.0)");
}

Prevention

When it happens

Trigger: A client hits the WS-Federation /federation endpoint (GET/POST handled by handleFederationRequest) and `WSFederationRequest.of(request).wa()` resolves to null or empty string — i.e. the `wa` parameter is absent, empty, or not propagated through a proxy.

Common situations: RP-generated sign-in messages missing the wa=wsignin1.0 parameter; reverse proxies or gateways stripping query strings; hand-built deep links to the CAS WS-Fed endpoint copied without full parameters; metadata/claim-rules rewriting the redirect URL and dropping parameters.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/f3fc5a5c6863ea3f. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-ws-idp/src/main/java/org/apereo/cas/ws/idp/web/WSFederationValidateRequestController.java:49

    public WSFederationValidateRequestController(final WSFederationRequestConfigurationContext ctx) {
        super(ctx);
    }

    /**
     * Handle federation request.
     *
     * @param response the response
     * @param request  the request
     * @throws Exception the exception
     */
    @GetMapping(path = WSFederationConstants.ENDPOINT_FEDERATION_REQUEST)
    @Operation(summary = "Handle federation request")
    public void handleFederationRequest(final HttpServletResponse response,
                                        final HttpServletRequest request) throws Exception {
        val fedRequest = WSFederationRequest.of(request);
        val wa = fedRequest.wa();
        if (StringUtils.isBlank(wa)) {
            throw new UnauthorizedAuthenticationException("Unable to determine the [WA] parameter", new HashMap<>());
        }

        switch (wa.toLowerCase(Locale.ENGLISH)) {
            case WSFederationConstants.WSIGNOUT10, WSFederationConstants.WSIGNOUT_CLEANUP10 -> handleLogoutRequest(fedRequest, request, response);
            case WSFederationConstants.WSIGNIN10 -> handleInitialAuthenticationRequest(fedRequest, response, request);
            default -> throw new UnauthorizedAuthenticationException("The authentication request is not recognized", new HashMap<>());
        }
    }

    protected void handleLogoutRequest(final WSFederationRequest fedRequest, final HttpServletRequest request,
                                       final HttpServletResponse response) throws Exception {

        val logoutUrl = FunctionUtils.doIf(StringUtils.isNotBlank(fedRequest.wreply()),
                () -> {
                    val service = createService(fedRequest);
                    val registeredService = getWsFederationRegisteredService(service);
                    LOGGER.debug("Invoking logout operation for request [{}], redirecting next to [{}] matched against [{}]",
                        fedRequest, fedRequest.wreply(), registeredService);

View on GitHub (pinned to e7288fc434)