From a563689e6c9c715e2405257235d46a1ff613ed0f Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Tue, 29 Aug 2017 21:19:42 -0500 Subject: [PATCH] Add PasswordEncoder for UserDetailsRepositoryAuthenticationManager --- ...etailsRepositoryAuthenticationManager.java | 12 ++++++- ...sRepositoryAuthenticationManagerTests.java | 35 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryAuthenticationManager.java b/core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryAuthenticationManager.java index cbc98b54ee..38a6000c4c 100644 --- a/core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryAuthenticationManager.java +++ b/core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryAuthenticationManager.java @@ -18,9 +18,12 @@ package org.springframework.security.authentication; +import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetailsRepository; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.util.Assert; import reactor.core.publisher.Mono; @@ -31,6 +34,8 @@ import reactor.core.publisher.Mono; public class UserDetailsRepositoryAuthenticationManager implements ReactiveAuthenticationManager { private final UserDetailsRepository repository; + private PasswordEncoder passwordEncoder = NoOpPasswordEncoder.getInstance(); + public UserDetailsRepositoryAuthenticationManager(UserDetailsRepository userDetailsRepository) { Assert.notNull(userDetailsRepository, "userDetailsRepository cannot be null"); this.repository = userDetailsRepository; @@ -41,8 +46,13 @@ public class UserDetailsRepositoryAuthenticationManager implements ReactiveAuthe final String username = authentication.getName(); return repository .findByUsername(username) - .filter( u -> u.getPassword().equals(authentication.getCredentials())) + .filter( u -> this.passwordEncoder.matches((String) authentication.getCredentials(), u.getPassword())) .switchIfEmpty( Mono.error(new BadCredentialsException("Invalid Credentials")) ) .map( u -> new UsernamePasswordAuthenticationToken(u, u.getPassword(), u.getAuthorities()) ); } + + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); + this.passwordEncoder = passwordEncoder; + } } diff --git a/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryAuthenticationManagerTests.java b/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryAuthenticationManagerTests.java index 1cdd49adef..1be9e0879d 100644 --- a/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryAuthenticationManagerTests.java +++ b/core/src/test/java/org/springframework/security/authentication/UserDetailsRepositoryAuthenticationManagerTests.java @@ -16,6 +16,7 @@ package org.springframework.security.authentication; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.when; import org.junit.Before; @@ -28,6 +29,7 @@ import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsRepository; +import org.springframework.security.crypto.password.PasswordEncoder; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -39,6 +41,8 @@ import reactor.test.StepVerifier; public class UserDetailsRepositoryAuthenticationManagerTests { @Mock UserDetailsRepository repository; + @Mock + PasswordEncoder passwordEncoder; UserDetailsRepositoryAuthenticationManager manager; String username; String password; @@ -94,4 +98,35 @@ public class UserDetailsRepositoryAuthenticationManagerTests { assertThat(authentication).isEqualTo(authentication); } + @Test + public void authenticateWhenPasswordEncoderAndSuccessThenSuccess() { + this.manager.setPasswordEncoder(this.passwordEncoder); + when(this.passwordEncoder.matches(any(), any())).thenReturn(true); + User user = new User(this.username, this.password, AuthorityUtils.createAuthorityList("ROLE_USER")); + when(this.repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user)); + + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( + this.username, this.password); + Authentication authentication = this.manager.authenticate(token).block(); + + assertThat(authentication).isEqualTo(authentication); + } + + @Test + public void authenticateWhenPasswordEncoderAndFailThenFail() { + this.manager.setPasswordEncoder(this.passwordEncoder); + when(this.passwordEncoder.matches(any(), any())).thenReturn(false); + User user = new User(this.username, this.password, AuthorityUtils.createAuthorityList("ROLE_USER")); + when(this.repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user)); + + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( + this.username, this.password); + + Mono authentication = this.manager.authenticate(token); + + StepVerifier + .create(authentication) + .expectError(BadCredentialsException.class) + .verify(); + } }