apereo/cas · warning

Missing web authn token from the request

Error message

Missing web authn token from the request

What it means

The WebAuthn session-validation webflow action expects a 'token' HTTP parameter carrying the WebAuthn credential token, but it is blank or absent, so doExecuteInternal logs a warning and transitions to authentication failure. No credential can be built without it.

Solutions

  1. Ensure the page/link that triggers WebAuthn session validation includes the token parameter (e.g. hidden form field or query string) exactly as generated by CAS.
  2. Check reverse proxies/URL rewriters aren't stripping or truncating the token query parameter.
  3. Restart the flow from the login page so CAS regenerates a fresh token rather than replaying an old URL.

Example fix

// before (form missing token)
<form method="post" action=".../webauthn/validate">...</form>

// after
<form method="post" action=".../webauthn/validate">
  <input type="hidden" name="token" th:value="${token}"/>
  ...
</form>
Defensive patterns

Strategy: validation

Validate before calling

// before invoking the WebAuthn validation action/endpoint
const token = params.get('token');
if (!token || token.trim() === '') {
  throw new Error('token parameter is required for WebAuthn session validation');
}

Prevention

When it happens

Trigger: WebAuthnValidateSessionCredentialTokenAction.doExecuteInternal reads request.getParameter("token") from the servlet request (via the webflow external context) and finds StringUtils.isBlank(token) — the validation link/POST omitting or emptying the token parameter.

Common situations: A custom login page or template dropped the hidden token field; an email/link-based WebAuthn validation flow where the user clicks a URL whose token query param got stripped by a proxy or URL sanitizer; user navigating directly to the validation URL without the token.

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/bcbf44c4c0ab4186. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-webauthn-core-webflow/src/main/java/org/apereo/cas/webauthn/web/flow/WebAuthnValidateSessionCredentialTokenAction.java:45

 * @since 6.3.0
 */
@RequiredArgsConstructor
@Slf4j
public class WebAuthnValidateSessionCredentialTokenAction extends AbstractMultifactorAuthenticationAction<WebAuthnMultifactorAuthenticationProvider> {
    protected final RegistrationStorage webAuthnCredentialRepository;

    protected final SessionManager sessionManager;

    protected final PrincipalFactory principalFactory;

    protected final TenantExtractor tenantExtractor;
    
    @Override
    protected @Nullable Event doExecuteInternal(final RequestContext requestContext) {
        val request = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext);
        val token = request.getParameter("token");
        if (StringUtils.isBlank(token)) {
            LOGGER.warn("Missing web authn token from the request");
            return eventFactory.event(this, CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE);
        }

        LOGGER.debug("Received web authn token [{}]", token);
        val credential = new WebAuthnCredential(token);
        WebUtils.putCredential(requestContext, credential);

        val session = sessionManager.getSession(request, WebAuthnCredential.from(credential));
        if (session.isEmpty()) {
            LOGGER.warn("Unable to locate existing session from the current token [{}]", token);
            return eventFactory.event(this, CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE);
        }
        val result = webAuthnCredentialRepository.getUsernameForUserHandle(session.get());
        if (result.isEmpty()) {
            LOGGER.warn("Unable to locate user based on the given user handle");
            return eventFactory.event(this, CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE);
        }
        val username = result.get();

View on GitHub (pinned to e7288fc434)