spring-projects/spring-security · error · AuthenticationCredentialsNotFoundException

SwitchUserFilter.noOriginalAuthentication

SwitchUserFilter.noOriginalAuthentication

Error message

Failed to find original user

What it means

When exiting impersonation, SwitchUserFilter extracts the original Authentication from the current one via getSourceAuthentication (looking for a SwitchUserGrantedAuthority with ROLE_PREVIOUS_AUTHENTICATION). If none is present, the current user was never actually switched, and AuthenticationCredentialsNotFoundException (SwitchUserFilter.noOriginalAuthentication) is thrown.

Source

Thrown at web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java:275

	 * @return The original <code>Authentication</code> object or <code>null</code>
	 * otherwise.
	 * @throws AuthenticationCredentialsNotFoundException If no
	 * <code>Authentication</code> associated with this request.
	 */
	protected Authentication attemptExitUser(HttpServletRequest request)
			throws AuthenticationCredentialsNotFoundException {
		// need to check to see if the current user has a SwitchUserGrantedAuthority
		Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
		if (current == null) {
			throw new AuthenticationCredentialsNotFoundException(this.messages
				.getMessage("SwitchUserFilter.noCurrentUser", "No current user associated with this request"));
		}
		// check to see if the current user did actual switch to another user
		// if so, get the original source user so we can switch back
		Authentication original = getSourceAuthentication(current);
		if (original == null) {
			this.logger.debug("Failed to find original user");
			throw new AuthenticationCredentialsNotFoundException(this.messages
				.getMessage("SwitchUserFilter.noOriginalAuthentication", "Failed to find original user"));
		}
		// get the source user details
		UserDetails originalUser = null;
		Object obj = original.getPrincipal();
		if ((obj != null) && obj instanceof UserDetails) {
			originalUser = (UserDetails) obj;
		}
		// publish event
		if (this.eventPublisher != null) {
			this.eventPublisher.publishEvent(new AuthenticationSwitchUserEvent(current, originalUser));
		}
		return original;
	}

	/**
	 * Create a switch user token that contains an additional <tt>GrantedAuthority</tt>
	 * that contains the original <code>Authentication</code> object.

View on GitHub (pinned to 96852e8860)

Solutions

  1. Only render/allow the exit-user endpoint when the current user holds a SwitchUserGrantedAuthority
  2. Handle AuthenticationCredentialsNotFoundException for the exit URL with a redirect to the home page instead of a 500/403
  3. Guard the exit URL with a request check or custom filter that verifies impersonation state
  4. Avoid double-clicking switch-back: after exit the authority is removed

Example fix

// before
boolean canExit = authentication != null;
// after
boolean canExit = authentication != null && authentication.getAuthorities().stream()
        .anyMatch(a -> a instanceof SwitchUserGrantedAuthority);
Defensive patterns

Strategy: type-guard

Validate before calling

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
boolean impersonating = auth != null && auth.getAuthorities().stream()
        .anyMatch(a -> a instanceof SwitchUserGrantedAuthority);
if (!impersonating) {
    response.sendRedirect(request.getContextPath() + "/");
    return;
}

Type guard

boolean isImpersonating(Authentication a) {
    return a != null && a.getAuthorities().stream()
        .anyMatch(SwitchUserGrantedAuthority.class::isInstance);
}

Try / catch

try {
    switchUserFilter.doFilter(request, response);
} catch (AuthenticationCredentialsNotFoundException e) {
    response.sendRedirect("/"); // not impersonating; nothing to switch back to
}

Prevention

When it happens

Trigger: attemptExitUser is invoked at the exit-user URL by a user whose Authentication contains no SwitchUserGrantedAuthority — i.e. calling /logout/impersonate while not impersonating anyone.

Common situations: User bookmarks or manually visits the exit URL; the switch-back link is rendered to all users instead of only impersonators; successful exit already consumed the previous-authentication authority and the user clicks it again.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/43aa356f63f32894. Report an issue: GitHub.