spring-projects/spring-security · error · AccessDeniedException
Can't change password as no Authentication object found in c
Error message
Can't change password as no Authentication object found in context for current user.
What it means
JdbcUserDetailsManager.changePassword requires an Authentication in the SecurityContextHolder to know which user's password to change; if none is present it throws AccessDeniedException. The class then optionally re-authenticates the user against the configured AuthenticationManager before performing the UPDATE. This mirrors InMemoryUserDetailsManager's behavior and is treated as a caller/configuration error.
Source
Thrown at core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java:319
public void deleteUser(String username) {
if (getEnableAuthorities()) {
deleteUserAuthorities(username);
}
requireJdbcTemplate().update(this.deleteUserSql, username);
this.userCache.removeUserFromCache(username);
}
private void deleteUserAuthorities(String username) {
requireJdbcTemplate().update(this.deleteUserAuthoritiesSql, username);
}
@Override
public void changePassword(@Nullable String oldPassword, @Nullable String newPassword)
throws AuthenticationException {
Authentication currentUser = this.securityContextHolderStrategy.getContext().getAuthentication();
if (currentUser == null) {
// This would indicate bad coding somewhere
throw new AccessDeniedException(
"Can't change password as no Authentication object found in context " + "for current user.");
}
String username = currentUser.getName();
// If an authentication manager has been set, re-authenticate the user with the
// supplied password.
if (this.authenticationManager != null) {
this.logger.debug(LogMessage.format("Reauthenticating user '%s' for password change request.", username));
this.authenticationManager
.authenticate(UsernamePasswordAuthenticationToken.unauthenticated(username, oldPassword));
}
else {
this.logger.debug("No authentication manager set. Password won't be re-checked.");
}
this.logger.debug("Changing password for user '" + username + "'");
requireJdbcTemplate().update(this.changePasswordSql, newPassword, username);
Authentication authentication = createNewAuthentication(currentUser, newPassword);
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
context.setAuthentication(authentication);View on GitHub (pinned to 96852e8860)
Solutions
- Invoke changePassword only within an authenticated context (authenticated request or explicit SecurityContextHolder.getContext().setAuthentication(...))
- In tests, use @WithMockUser or set an Authentication in the SecurityContextHolder before the call
- Wire an AuthenticationManager into JdbcUserDetailsManager so re-authentication with oldPassword works as intended
- For unauthenticated reset flows, look up the user directly and update via JDBC or an admin path instead of changePassword
Example fix
// before
jdbcManager.changePassword("old", "new"); // AccessDeniedException
// after
Authentication auth = new UsernamePasswordAuthenticationToken("alice", null);
SecurityContextHolder.getContext().setAuthentication(auth);
jdbcManager.changePassword("old", "new"); Defensive patterns
Strategy: try-catch
Validate before calling
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth instanceof AnonymousAuthenticationToken) {
throw new AccessDeniedException("Authentication required to change password");
} Type guard
static boolean hasAuthentication() {
Authentication a = SecurityContextHolder.getContext().getAuthentication();
return a != null && a.isAuthenticated();
} Try / catch
try {
jdbcManager.changePassword(oldPassword, newPassword);
} catch (AccessDeniedException e) {
if (e.getMessage().contains("no Authentication object")) {
// force re-login before password change
} else if (e instanceof AuthenticationException) {
// oldPassword re-authentication failed
} else { throw e; }
} Prevention
- Gate password-change endpoints behind authentication in the security filter chain
- Set an Authentication explicitly in tests and background jobs
- Configure an AuthenticationManager on JdbcUserDetailsManager for old-password verification
- Keep SecurityContext propagation enabled (SecurityContextHolder.MODE_INHERITABLETHREADLOCAL or executors)
When it happens
Trigger: Calling changePassword when the current thread has no authenticated SecurityContext; running inside a scheduled job or message listener without propagating SecurityContext; a security filter chain that never populates the context for the endpoint; unit tests invoking the method directly without authentication.
Common situations: Password reset flows implemented as unauthenticated endpoints; integration tests missing @WithMockUser; Spring remoting/async execution dropping the context between request and password change.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Authenticated principal required to operate with ACLs
- Can't change password as no Authentication object found in c
- JdbcDaoImpl.notFound
- JdbcDaoImpl.noAuthority
- An Authentication object was not found in the SecurityContex
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/b9a54300aede523c.
Report an issue: GitHub.