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

  1. Request a new passwordless token and use the most recent one immediately.
  2. Check that the link/code was not truncated by the mail/SMS client (whitespace or HTML encoding of the token).
  3. Ensure the passwordless account lookup (username) matches the user who requested the token.
  4. 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

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


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)