apereo/cas · warning
Unable to locate existing session from the current token
Error message
Unable to locate existing session from the current token [{}] What it means
A WebAuthn token was provided, but sessionManager.getSession(request, ...) for the token's derived identity returns empty, so the action cannot correlate the token to an existing server-side WebAuthn session and fails authentication. The token references a session CAS no longer holds.
Solutions
- Restart the WebAuthn MFA flow from the login page to obtain a fresh token and session.
- If running multiple CAS nodes, configure a shared session store (e.g. distributed sessions via Redis/Hazelcast) or sticky sessions so getSession can find the token's session.
- Increase the WebAuthn/session timeout configuration if legitimate users take too long to complete the ceremony.
Example fix
// before (in-memory session per node) // no shared session config // after: enable shared session storage across CAS nodes # e.g. spring session backed by redis spring.session.store-type=redis spring.redis.host=redis.internal
Defensive patterns
Strategy: fallback
Validate before calling
// before starting the WebAuthn ceremony, confirm an active session exists server-side
if (!casSessionStore.exists(webAuthnSessionKey)) {
// redirect user to re-initiate the MFA flow instead of failing
} Try / catch
try {
var session = sessionManager.getSession(request, WebAuthnCredential.from(credential));
} catch (Exception e) {
// fall back to restarting the WebAuthn flow with a fresh token
} Prevention
- Use shared session storage or sticky sessions in multi-node CAS deployments.
- Size session/TTL timeouts so users can realistically complete the WebAuthn ceremony.
- Treat CAS restarts as invalidating in-flight WebAuthn sessions; don't reuse old links.
When it happens
Trigger: In doExecuteInternal, after building WebAuthnCredential from the token, WebAuthnCredential.from(credential) is used to look up the managed session; session.isEmpty() fires when the session expired, was evicted (restart or session store flush), or the token was issued by a different CAS node without shared session storage.
Common situations: User delays and the WebAuthn session times out; CAS restarted or session store (e.g. in-memory, Redis without proper persistence/TTL config) lost entries; load-balanced CAS without sticky sessions or shared session backend.
Related errors
- No registration records could be found for
- Missing web authn token from the request
- 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/dd4b1f63f578a3e7.
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:55
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();
return FunctionUtils.doUnchecked(() -> {
val authentication = DefaultAuthenticationBuilder.newInstance()
.addCredential(credential)
.setPrincipal(principalFactory.createPrincipal(username))
.build();
LOGGER.debug("Finalized authentication attempt based on [{}]", authentication);
WebUtils.putAuthentication(authentication, requestContext);
return eventFactory.event(this, CasWebflowConstants.TRANSITION_ID_FINALIZE);
});
}View on GitHub (pinned to e7288fc434)