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
- Only render/allow the exit-user endpoint when the current user holds a SwitchUserGrantedAuthority
- Handle AuthenticationCredentialsNotFoundException for the exit URL with a redirect to the home page instead of a 500/403
- Guard the exit URL with a request check or custom filter that verifies impersonation state
- 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
- Only expose /logout/impersonate when ROLE_PREVIOUS_AUTHENTICATION is present
- Redirect rather than error when exit is requested without impersonation
- Strip impersonation state on double exit attempts
- Add integration tests for exit URL hit without prior switch
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.