apereo/cas · error · AuthenticationException
Provided token is not issued by and does not belong to
Error message
Provided token is not issued by and does not belong to
What it means
AuthenticationException thrown by AcceptPasswordlessAuthenticationAction when the token submitted in the request does not match the stored passwordless token retrieved for the user account. The action looks up the user's PasswordlessToken and requires an exact case-insensitive-equal match; any mismatch aborts the flow and surfaces an error event.
Solutions
- Request a new passwordless token and use the most recent one immediately.
- Check that the link/code was not truncated by the mail/SMS client (whitespace or HTML encoding of the token).
- Ensure the passwordless account lookup (username) matches the user who requested the token.
- If tokens keep expiring, increase the token expiration policy in the passwordless configuration.
Defensive patterns
Strategy: validation
Validate before calling
// Compare tokens before invoking the action
Optional<PasswordlessToken> tok = repo.findToken(username);
if (tok.isEmpty() || !tok.get().getToken().equalsIgnoreCase(submittedToken)) {
return error("token mismatch");
} Try / catch
try { action.execute(ctx); } catch (AuthenticationException e) { flashError("invalid token; request a new one"); return errorEvent; } Prevention
- Always use the most recently issued token/link.
- Guard email/SMS rendering so token strings are not truncated or HTML-mangled.
- Inform users that old codes become invalid when a new one is requested.
When it happens
Trigger: User submits a token string in the passwordless webflow that differs from passwordlessToken.getToken() for the resolved passwordless user account (token typed incorrectly, stale token from a previous request, or token for a different user).
Common situations: User opens an old email/SMS link with an already-replaced token; user retypes the code with a typo; multiple passwordless requests invalidated each other; the repository returned a token generated after the user's submission.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unable to locate authentication object in the webflow…
- Unable to determine authentication from the request context
- Failed to authenticate code
- Authentication chain is empty as no authentications have…
- Adaptive authentication policy does not allow this request…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/bbf10d82ee875518.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-passwordless-webflow/src/main/java/org/apereo/cas/web/flow/AcceptPasswordlessAuthenticationAction.java:69
this.passwordlessTokenRepository = passwordlessTokenRepository;
this.authenticationSystemSupport = authenticationSystemSupport;
this.passwordlessUserAccountStore = passwordlessUserAccountStore;
}
@Override
protected @Nullable Event doExecuteInternal(final RequestContext requestContext) throws Throwable {
val passwordlessUserAccount = Objects.requireNonNull(PasswordlessWebflowUtils.getPasswordlessAuthenticationAccount(requestContext, PasswordlessUserAccount.class));
try {
val token = requestContext.getRequestParameters().getRequired("token");
val passwordlessToken = passwordlessTokenRepository.findToken(passwordlessUserAccount.getUsername())
.orElseThrow(() -> new AuthenticationException("Unable to find passwordless token for " + passwordlessUserAccount.getUsername()));
if (passwordlessToken.getToken().equalsIgnoreCase(token)) {
handlePasswordlessAuthenticationAttempt(requestContext, passwordlessUserAccount, passwordlessToken);
val finalEvent = super.doExecuteInternal(requestContext);
passwordlessTokenRepository.deleteToken(passwordlessToken);
return finalEvent;
}
throw new AuthenticationException("Provided token " + token + " is not issued by and does not belong to " + passwordlessUserAccount.getUsername());
} catch (final Throwable e) {
LoggingUtils.error(LOGGER, e);
val attributes = new LocalAttributeMap<>();
attributes.put("error", e);
val request = PasswordlessAuthenticationRequest.builder()
.username(passwordlessUserAccount.getUsername())
.build();
var account = passwordlessUserAccountStore.findUser(request);
account.ifPresent(o -> attributes.put("passwordlessAccount", passwordlessUserAccount));
return eventFactory.event(this, CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE, attributes);
}
}
protected void handlePasswordlessAuthenticationAttempt(final RequestContext requestContext, final PasswordlessUserAccount principal,
final PasswordlessAuthenticationToken token) throws Throwable {
val credential = new OneTimePasswordCredential(principal.getUsername(), token.getToken());
val service = WebUtils.getService(requestContext);
var authenticationResultBuilder = authenticationSystemSupport.handleInitialAuthenticationTransaction(service, credential);View on GitHub (pinned to e7288fc434)