Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UserDetailsService Constructor #15984

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,10 @@ else if (userDetailsServices.size() > 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 @@ -66,8 +66,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