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
- 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.
- Check reverse proxies/URL rewriters aren't stripping or truncating the token query parameter.
- 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
- Always render the generated token in the hidden form field or link that triggers validation.
- Check proxies/URL sanitizers don't strip the token query parameter.
- Have users restart the flow from login when the validation link has no token.
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
- No registration records could be found for
- Unable to locate existing session from the current token
- State [ : : ] does not have a matching transition for
- Unknown Duo Security authentication attempt
- Failed to authenticate code
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)