Skip to content

Commit

Permalink
Add UserDetailsService Constructor
Browse files Browse the repository at this point in the history
Closes gh-15973
  • Loading branch information
jzheaux committed Dec 17, 2024
1 parent f45cc22 commit b9f3a28
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,10 @@ else if (beanNames.length > 1) {
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
CompromisedPasswordChecker passwordChecker = getBeanOrNull(CompromisedPasswordChecker.class);
DaoAuthenticationProvider provider;
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
if (passwordEncoder != null) {
provider = new DaoAuthenticationProvider(passwordEncoder);
provider.setPasswordEncoder(passwordEncoder);
}
else {
provider = new DaoAuthenticationProvider();
}
provider.setUserDetailsService(userDetailsService);
if (passwordManager != null) {
provider.setUserDetailsPasswordService(passwordManager);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
public abstract class AbstractDaoAuthenticationConfigurer<B extends ProviderManagerBuilder<B>, C extends AbstractDaoAuthenticationConfigurer<B, C, U>, U extends UserDetailsService>
extends UserDetailsAwareConfigurer<B, U> {

private DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
private DaoAuthenticationProvider provider;

private final U userDetailsService;

Expand All @@ -46,7 +46,7 @@ public abstract class AbstractDaoAuthenticationConfigurer<B extends ProviderMana
*/
AbstractDaoAuthenticationConfigurer(U userDetailsService) {
this.userDetailsService = userDetailsService;
this.provider.setUserDetailsService(userDetailsService);
this.provider = new DaoAuthenticationProvider(userDetailsService);
if (userDetailsService instanceof UserDetailsPasswordService) {
this.provider.setUserDetailsPasswordService((UserDetailsPasswordService) userDetailsService);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ public AuthenticationManager getObject() throws Exception {
if (uds == null) {
throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER, MISSING_BEAN_ERROR_MESSAGE);
}
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(uds);
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(uds);
PasswordEncoder passwordEncoder = this.bf.getBeanProvider(PasswordEncoder.class).getIfUnique();
if (passwordEncoder != null) {
provider.setPasswordEncoder(passwordEncoder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.springframework.security.authentication.dao;

import java.util.function.Supplier;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
Expand All @@ -31,6 +33,7 @@
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;
import org.springframework.util.function.SingletonSupplier;

/**
* An {@link AuthenticationProvider} implementation that retrieves user details from a
Expand All @@ -48,7 +51,8 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
*/
private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";

private PasswordEncoder passwordEncoder;
private Supplier<PasswordEncoder> passwordEncoder = SingletonSupplier
.of(PasswordEncoderFactories::createDelegatingPasswordEncoder);

/**
* The password used to perform {@link PasswordEncoder#matches(CharSequence, String)}
Expand All @@ -64,15 +68,25 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication

private CompromisedPasswordChecker compromisedPasswordChecker;

/**
* @deprecated Please provide the {@link UserDetailsService} in the constructor
*/
@Deprecated
public DaoAuthenticationProvider() {
this(PasswordEncoderFactories.createDelegatingPasswordEncoder());
}

public DaoAuthenticationProvider(UserDetailsService userDetailsService) {
setUserDetailsService(userDetailsService);
}

/**
* Creates a new instance using the provided {@link PasswordEncoder}
* @param passwordEncoder the {@link PasswordEncoder} to use. Cannot be null.
* @since 6.0.3
* @deprecated Please provide the {@link UserDetailsService} in the constructor
* followed by {@link #setPasswordEncoder(PasswordEncoder)} instead
*/
@Deprecated
public DaoAuthenticationProvider(PasswordEncoder passwordEncoder) {
setPasswordEncoder(passwordEncoder);
}
Expand All @@ -87,7 +101,7 @@ protected void additionalAuthenticationChecks(UserDetails userDetails,
.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
String presentedPassword = authentication.getCredentials().toString();
if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
if (!this.passwordEncoder.get().matches(presentedPassword, userDetails.getPassword())) {
this.logger.debug("Failed to authenticate since password does not match stored value");
throw new BadCredentialsException(this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
Expand Down Expand Up @@ -133,24 +147,24 @@ protected Authentication createSuccessAuthentication(Object principal, Authentic
throw new CompromisedPasswordException("The provided password is compromised, please change your password");
}
boolean upgradeEncoding = this.userDetailsPasswordService != null
&& this.passwordEncoder.upgradeEncoding(user.getPassword());
&& this.passwordEncoder.get().upgradeEncoding(user.getPassword());
if (upgradeEncoding) {
String newPassword = this.passwordEncoder.encode(presentedPassword);
String newPassword = this.passwordEncoder.get().encode(presentedPassword);
user = this.userDetailsPasswordService.updatePassword(user, newPassword);
}
return super.createSuccessAuthentication(principal, authentication, user);
}

private void prepareTimingAttackProtection() {
if (this.userNotFoundEncodedPassword == null) {
this.userNotFoundEncodedPassword = this.passwordEncoder.encode(USER_NOT_FOUND_PASSWORD);
this.userNotFoundEncodedPassword = this.passwordEncoder.get().encode(USER_NOT_FOUND_PASSWORD);
}
}

private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken authentication) {
if (authentication.getCredentials() != null) {
String presentedPassword = authentication.getCredentials().toString();
this.passwordEncoder.matches(presentedPassword, this.userNotFoundEncodedPassword);
this.passwordEncoder.get().matches(presentedPassword, this.userNotFoundEncodedPassword);
}
}

Expand All @@ -163,14 +177,19 @@ private void mitigateAgainstTimingAttack(UsernamePasswordAuthenticationToken aut
*/
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
this.passwordEncoder = passwordEncoder;
this.passwordEncoder = () -> passwordEncoder;
this.userNotFoundEncodedPassword = null;
}

protected PasswordEncoder getPasswordEncoder() {
return this.passwordEncoder;
return this.passwordEncoder.get();
}

/**
* @param userDetailsService
* @deprecated Please provide the {@link UserDetailsService} in the constructor
*/
@Deprecated
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,7 @@ public class SecurityConfig {
public AuthenticationManager authenticationManager(
UserDetailsService userDetailsService,
PasswordEncoder passwordEncoder) {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder);
return new ProviderManager(authenticationProvider);
Expand Down Expand Up @@ -229,8 +228,7 @@ class SecurityConfig {
fun authenticationManager(
userDetailsService: UserDetailsService,
passwordEncoder: PasswordEncoder): AuthenticationManager {
val authenticationProvider = DaoAuthenticationProvider()
authenticationProvider.setUserDetailsService(userDetailsService)
val authenticationProvider = DaoAuthenticationProvider(userDetailsService)
authenticationProvider.setPasswordEncoder(passwordEncoder)
return ProviderManager(authenticationProvider)
Expand Down Expand Up @@ -501,8 +499,7 @@ class SecurityConfig {
@Bean
fun authenticationManager(): AuthenticationManager {
val authenticationProvider = DaoAuthenticationProvider()
authenticationProvider.setUserDetailsService(userDetailsService())
val authenticationProvider = DaoAuthenticationProvider(userDetailsService())
authenticationProvider.setPasswordEncoder(passwordEncoder())
val providerManager = ProviderManager(authenticationProvider)
Expand Down

0 comments on commit b9f3a28

Please sign in to comment.