How to turn off Spring Boot Encoder - java

I need to turn off encoder in my Spring boot project. It seems easy - just delete methods and variables, but then I get the error:
There is no PasswordEncoder mapped for the id "null"
Now, i have hardcoded user login and (encoded) password in my database. Password is stored as many literals and numbers, and in password word it means "123", and i need password to be "123" in database. Here is my code:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsServiceImpl userDetailsService;
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().
antMatchers("/", "/login", "/logout", "productPage", "contactsPage", "/register", "/add_person").permitAll();
http.authorizeRequests().
antMatchers("/admin","/view_person")
.access("hasAnyRole('ROLE_ADMIN', 'ROLE_SUPER_ADMIN')");
http.authorizeRequests().
and().exceptionHandling().accessDeniedPage("/403");
http.authorizeRequests().and().formLogin()//
.loginProcessingUrl("/j_spring_security_check")
.loginPage("/login")//
.defaultSuccessUrl("/productPage")//
.failureUrl("/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/logoutSuccessful")
.and().rememberMe().key("secret").tokenValiditySeconds(500000);
}
}
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private AppUserDao appUserDAO;
#Autowired
private AppRoleDao appRoleDAO;
#Override
public UserDetails loadUserByUsername(String name) {
AppUser appUser = this.appUserDAO.findUserAccount(name);
if (appUser == null) {
System.out.println("User not found! " + name);
throw new UsernameNotFoundException("User " + name + " was not found in the database");
}
System.out.println("Found User: " + appUser);
List<String> roleNames = this.appRoleDAO.getRoleNames(appUser.getId());
List<GrantedAuthority> grantList = new ArrayList<>();
if (roleNames != null) {
for (String role : roleNames) {
GrantedAuthority authority = new SimpleGrantedAuthority(role);
grantList.add(authority);
}
}
UserDetails userDetails = new User(appUser.getName(),
appUser.getPassword(), grantList);
return userDetails;
}
}
I can give any other classes if needed

Instead of your BCryptPassworencoder, use the following (though that's absolutely not recommended for production). This will not hash your password inputs, which is what you seem to want.
#Bean
public PasswordEncoder passwordEncoder() {
return new NoOpPasswordEncoder.getInstance();
}

Related

Spring Boot 2.7.5 Security 401 Unuathorized

I'm struggling with 401 unuathorized in postman while i try to enter a secured endpoint, I'm passing correct data, but spring security doesn't pass me on, I think I might miss something in DetailsService or somewhere Creating new user
Trying to authorize
Security config
#EnableWebSecurity
#RequiredArgsConstructor
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
private final CustomAuthProvider provider;
private final AuthenticationFailureHandler failureHandler;
#Bean
public AuthenticationManager authenticationManager (HttpSecurity http) throws Exception {
AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class);
builder.authenticationProvider(provider);
return builder.build();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests(auth -> {
auth.antMatchers(HttpMethod.POST, "/register").permitAll();
auth.antMatchers(HttpMethod.POST, "/login").hasRole("USER");
auth.antMatchers("/user/**").permitAll();
auth.antMatchers("/getusers").hasRole("USER");
auth.antMatchers("/moderator/**").hasRole("MODERATOR");
auth.antMatchers("/admin/**").hasRole("ADMIN");
})
.httpBasic(withDefaults())
.sessionManagement()
.sessionCreationPolicy(STATELESS);
return http.build();
}
Details Service
#Service
#RequiredArgsConstructor // Generates a constructor with required arguments.
public class DetailsService implements UserDetailsService {
private final UserService userService;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
var user = userService.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("Couldn't find \""+ username +"\" username");
}
if (user.getRoles() == null || user.getRoles().isEmpty()) {
throw new RuntimeException("User \"" + username + "\" has no roles");
}
Collection<GrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
return new User(user.getUsername(), user.getPassword(), user.isActive(),
!user.isExpired(), !user.isCredentialsexpired(), !user.isBlocked(), authorities);
}
Method with creating roles
#RequiredArgsConstructor
#Component
public class ApplicationStartRunner implements CommandLineRunner {
private final RoleRepository roleRepository;
#Override
public void run(String... args) throws Exception {
Role roleUser = new Role(1L, "123", "ROLE_USER");
Role roleModerator = new Role(2L, "456", "ROLE_MODERATOR");
Role roleAdmin = new Role(3L, "789", "ROLE_ADMIN");
roleRepository.saveAll(List.of(roleUser, roleAdmin, roleModerator));
}
EDIT: That's my password encoder bean
#Configuration
public class SecurityConfig {
#Bean
PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
And register method
#Override
public UserDTO createUser(RegisterDTO user) {
if (user.equals(userRepository.findByUsername(user.getUsername()))) {
throw new RuntimeException("This nickname is already taken");
}
if (user.equals(userRepository.findByEmail(user.getEmail()))) {
throw new RuntimeException("This email is already taken");
}
// Encoding password
user.setPassword(encoder.encode(user.getPassword()));
// On creating new Account it's going to have USER role
Role role = roleRepository.findByName("ROLE_USER");
String username = user.getUsername();
String password = user.getPassword();
String email = user.getEmail();
User dto = buildUser(username, password, email, role);
userRepository.save(dto);
return UserDTO.builder()
.username(username)
.password(password)
.email(email)
.build();
}
I think this is pretty clear.
That /getusers endpoint is protected and user must have USER role which obviously don't have. By default I think it should be ROLE_USER as spring is using that ROLE_ prefix. But you can specify any role that should be fetched from DB during user authorization.

Spring security with user/password

So I followed some guides on spring security with usernames and passwords, however most of them show using "InMemoryUserDetailsManager" which they say should not be used in production:
#Bean
public InMemoryUserDetailsManager userDetailsManager(){
UserDetails admin = User.withDefaultPasswordEncoder()
.username("ADMIN")
.password("123")
.roles("ADMIN").build();
return new InMemoryUserDetailsManager(admin);
}
My questions, so how should a production level version of this be setup? Is it just not using the default password encoder because it is deprecated or should I use an entirely different method of adding and storing users?
You should implement jdbc authentication DaoAuthenticationProvider. Checkout https://www.baeldung.com/spring-security-jdbc-authentication.
Your user details must be stored in permanent storage, not temporary storage. Also, passwords must be encrypted to avoid compromising security. So using permanent storage you can take backup or data and run queries out of it.
You can implement custom user details service instead of using default.
#Service
public class CustomUserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
#Autowired
private PasswordEncoder passwordEncoder;
#Autowired
public CustomUserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user == null) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.NOT_FOUND, "user");
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.getEnabled(),
true,
true,
true,
getAuthorities(user));
}
public Boolean isTokenValid(String token) {
try {
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(SECRET.getBytes()).parseClaimsJws(token);
return true;
} catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException ex) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.LOGIN_FAILURE, "invalid credentials");
} catch (ExpiredJwtException ex) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.LOGIN_FAILURE, "token expired");
}
}
#Transactional
public Boolean save(User user){
if(StringUtils.isEmpty(user.getUsername())) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "username");
}
if(StringUtils.isEmpty(user.getPassword())) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "password");
}
if(StringUtils.isEmpty(user.getEmail())) {
throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "email");
}
User registeredUser = new User();
registeredUser.setUsername(user.getUsername());
registeredUser.setPassword(passwordEncoder.encode(user.getPassword()));
registeredUser.setEmail(user.getEmail());
registeredUser.setEnabled(true);
registeredUser.setRoles(user.getRoles());
User savedUser = userRepository.save(registeredUser);
Inventory userInventory = inventoryService.saveInventoryForUser(savedUser.getUsername());
return userInventory != null;
}
private Set<GrantedAuthority> getAuthorities(User user){
Set<GrantedAuthority> authorities = new HashSet<>();
for(Role role : user.getRoles()) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getName().getRole());
authorities.add(grantedAuthority);
}
return authorities;
}
}
You can save user details into your repository.
#Repository
public interface UserRepository extends BaseRepository<User> {
User findByUsername(String username);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);
}
Finally add your user details into authentication manager with password encoder.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserRepository userRepository;
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsServiceBean()).passwordEncoder(passwordEncoder());
}
#Override
public UserDetailsService userDetailsServiceBean() {
return new CustomUserDetailsServiceImpl(userRepository);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
For more details check my github repository
Hello Please Code as the following coding
#Bean
public InMemoryUserDetailsManager createUserDetailsManager() {
UserDetails userDetails1 = createNewUser("username1", "dummy");
UserDetails userDetails2 = createNewUser("username2", "dummydummy");
return new InMemoryUserDetailsManager(userDetails1, userDetails2);
}
private UserDetails createNewUser(String username, String password) {
Function<String, String> passwordEncoder
= input -> passwordEncoder().encode(input);
UserDetails userDetails = User.builder()
.passwordEncoder(passwordEncoder)
.username(username)
.password(password)
.roles("USER","ADMIN")
.build();
return userDetails;
}
Hope it help you

The dependencies of some of the beans in the application context form a cycle email sender

Cycle is formed after adding EmailSender code.
I did everything just by tutorials.
And then I got that error, tbh I didn't get how this cycle works, but I tried, though couldn't find this connection between classes.
application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/med
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=
spring.mail.password=
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
Here is my security config, JavaMailSender bean was firstly in EmailSenderImpl, but I got similar problem with cycle, but the picture was another.
SecurityConfig:
#Configuration
#EnableWebSecurity
#RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
#Value("${spring.mail.username}")
private String username;
#Value("${spring.mail.password}")
private String password;
#Value("${spring.mail.host}")
private String host;
#Value("${spring.mail.port}")
private int port;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(STATELESS)
.and()
.authorizeRequests().antMatchers("/login/**", "/api/v1/user/token/refresh/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new AuthenticationFilter(authenticationManagerBean()))
.addFilterBefore(new AuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public JavaMailSender getJavaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(host);
mailSender.setPort(port);
mailSender.setUsername(username);
mailSender.setPassword(password);
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.debug", "true");
return mailSender;
}
}
This class actually calls email method.
UserImpl:
#RequiredArgsConstructor
#Service("userImpl")
public class UserImpl implements UserService, UserDetailsService {
private final UserRepository userRepository;
private final EmailSenderService emailSenderService;
#Override
public List<User> getUsers() {
return userRepository.findAll();
}
#Override
public User getUserById(Long id) {
User user = userRepository.findById(id).orElseThrow();
return user;
}
#Override
public User getUserByEmail(String email) {
User user = userRepository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("User was not found with email: " + email);
}
return user;
}
#Override
public User registerUser(User user) {
emailSenderService.sendOTPEmail(user.getEmail());
user.setPassword(passwordEncoder().encode(user.getPassword()));
return userRepository.save(user);
}
#Override
public User updateUser(UserModel userModel) {
return null;
}
#Override
public User deleteUser(Long id) {
return null;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByEmail(username);
if (user == null) {
throw new UsernameNotFoundException("User was not found with email: " + username);
}
return UserModel.getUserDetails(user);
}
protected PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public static UserModel toUserModel(User user) {
UserModel userModel = new UserModel();
userModel.setUserId(user.getUserId());
userModel.setEmail(user.getEmail());
userModel.setPassword(user.getPassword());
userModel.setPhoneNumber(user.getPhoneNumber());
userModel.setOtpUsed(user.isOtpUsed());
userModel.setRole(user.getRole());
userModel.setStatus(user.getStatus());
return userModel;
}
}
Here is sendotp method which had to work and before in sendOTPEmail method instead of String email it was User user, but I though calling entity is the source of problem which it wasn't.
EmailSenderImpl:
#Service
public class EmailSenderImpl implements EmailSenderService {
private final JavaMailSender mailSender;
public EmailSenderImpl(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
#SneakyThrows
#Override
public void sendOTPEmail(String email) {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
char[] otp = generateOtp();
helper.setFrom("tilekzh0701#gmail.com");
helper.setTo(email);
String subject = "Here's your One Time Password (OTP) - Expire in 5 minutes!";
String content = "<p>Hello! </p>"
+ "<p>For security reason, you're required to use the following "
+ "One Time Password to login:</p>"
+ "<p><b>" + Arrays.toString(otp) + "</b></p>"
+ "<br>"
+ "<p>Note: this OTP is set to expire in 5 minutes.</p>";
helper.setSubject(subject);
helper.setText(content, true);
mailSender.send(message);
}
static char[] generateOtp()
{
String Capital_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String Small_chars = "abcdefghijklmnopqrstuvwxyz";
String numbers = "0123456789";
String symbols = "!##$%^&*_=+-/.?<>)";
String values = Capital_chars + Small_chars + numbers + symbols;
Random random = new Random();
char[] password = new char[8];
for (int i = 0; i < 8; i++)
{
password[i] = values.charAt(random.nextInt(values.length()));
}
return password;
}
}
Here is issue. Hope to get a help.
Run:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-06-21 09:44:13.078 ERROR 12284 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfig defined in file [C:\Users\User\Desktop\project\medtech\target\classes\com\project\medtech\config\SecurityConfig.class]
↑ ↓
| userImpl defined in file [C:\Users\User\Desktop\project\medtech\target\classes\com\project\medtech\service\UserImpl.class]
↑ ↓
| emailSenderImpl defined in file [C:\Users\User\Desktop\project\medtech\target\classes\com\project\medtech\service\EmailSenderImpl.class]
└─────┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

How to get logged user id in REST API

I have built a Java application with the REST API convention. I working on endpoint which returns objects only if object is connected with user by common id in database(ManyToOne annotation). In order to achieve that i need current logged user id for comapring it with object's user id. If Ids are the same, endpoint returns data. I know solutions as "Principal" or "Authentication" classes but they provide everything except of "id". I used spring security http basic for authentication.
My authentication classes:
#Component
public class CustomAuthenticator implements AuthenticationProvider {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
#Autowired
public CustomAuthenticator(UserRepository userRepository, #Lazy PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String login = authentication.getName();
String password = authentication.getCredentials().toString();
User user = userRepository.findByLogin(login).orElseThrow(() -> new EntityNotFoundException("User not found"));
if (!passwordEncoder.matches(password, user.getPassword())) {
throw new BadCredentialsException("Bad credentials");
}
return new UsernamePasswordAuthenticationToken(login, password, convertAuthorities(user.getRoles()));
}
private Set<GrantedAuthority> convertAuthorities(Set<UserRole> userRoles) {
Set<GrantedAuthority> authorities = new HashSet<>();
for (UserRole ur : userRoles) {
authorities.add(new SimpleGrantedAuthority(ur.getRole().toString()));
}
return authorities;
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
SECURITY CONFIG CLASS:
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CustomAuthenticator customAuthenticator;
public SecurityConfig(CustomAuthenticator customAuthenticator) {
this.customAuthenticator = customAuthenticator;
}
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
return passwordEncoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/api").permitAll()
.antMatchers("/api/register").permitAll()
//TODO everybody now has access to database, change it later
.antMatchers("/h2-console/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
http
.csrf().disable()
.headers().frameOptions().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticator);
}
}
Does someone know how to resolve that problem ?
You can use UserDetails class and set id for the username field, this class provides by spring security.
If you don't want that solution, you can create a Subclass extend UserDetails class and decide an id field. When receiving the request, parse principal to UserDetails or subclass extends UserDetails to get the id
Ex:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails userPrincipal = (UserDetails)authentication.getPrincipal();

loadUserByUsername execute twice using DaoAuthenticationProvider

I am using DaoAuthenticationProvider for authenciation but when I submit form loadUserByUsername is called twice by super.authenticate(authentication) intially it throws BadCredentialsException and then next time it login successfully
This process is working fine if I do not use passwordencoder but when I use it loadUserByUsername method is called twice.
Below is my code:
SecurityConfig
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("authenticationProvider")
AuthenticationProvider authenticationProvider;
#Autowired
#Qualifier("userDetailsService")
UserDetailsService userDetailsService;
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(authenticationProvider)
.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin/**")
.access("hasRole('ROLE_ADMIN')").and().formLogin()
.loginPage("/login").failureUrl("/login?error")
.usernameParameter("username").passwordParameter("password")
.and().logout().logoutSuccessUrl("/login?logout").and().csrf()
.and().exceptionHandling().accessDeniedPage("/403");
}
}
Authentication class
#Component("authenticationProvider")
public class LimitLoginAuthenticationProvider extends DaoAuthenticationProvider {
#Autowired
#Qualifier("userDetailsService")
#Override
public void setUserDetailsService(UserDetailsService userDetailsService) {
super.setUserDetailsService(userDetailsService);
}
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
try {
System.out.println("inside authenticate");
Authentication auth = super.authenticate(authentication);
return auth;
} catch (BadCredentialsException be) {
System.out.println("First call comes here ");
throw be;
} catch (LockedException e) {
throw e;
}
}
}
MyUserdetailsService class implments UserDetailsService
#Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
#Autowired
private UserDao userDao;
/* below method is called twice if I am using passwordencoder,
initially authentication fails and then again immediately
on second call authentication succeed */
#Transactional(readOnly=true)
#Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
com.mkyong.users.model.User user = userDao.findByUserName(username);
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole());
return buildUserForAuthentication(user, authorities);
}
private User buildUserForAuthentication(com.mkyong.users.model.User user, List<GrantedAuthority> authorities) {
MyUserDetails myUserDetails = new MyUserDetails (user.getUsername(), user.getPassword(), user.isEnabled(), user.isAccountNonExpired(), user.isAccountNonLocked(), user.isCredentialsNonExpired(), user.getEmailId(),authorities);
return myUserDetails;
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
}
Can some please help me. I believe there is some change needed in SecurityConfig class but exactly where I am not able to figure out.
Finally after help from java_dude and SergeBallesta I got the resolution for my query.
After a lot of debug I saw that when isPasswordValid method was getting called inside DaoAuthenticationProvider class instead of calling method 1 it was calling method 2 from org.springframework.security.authentication.encoding.PlaintextPasswordEncoder which one is depreciated and on second call it was calling proper isPasswordValid
method 1.
Method 1
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
checkSalt(salt);
return delegate.matches(rawPass, encPass);
}
Method 2
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
String pass1 = encPass + "";
// Strict delimiters is false because pass2 never persisted anywhere
// and we want to avoid unnecessary exceptions as a result (the
// authentication will fail as the encodePassword never allows them)
String pass2 = mergePasswordAndSalt(rawPass, salt, false);
if (ignorePasswordCase) {
// Note: per String javadoc to get correct results for Locale insensitive, use English
pass1 = pass1.toLowerCase(Locale.ENGLISH);
pass2 = pass2.toLowerCase(Locale.ENGLISH);
}
return PasswordEncoderUtils.equals(pass1,pass2);
}
To work authentication properly just add below code in your SecurityConfig class in addittion to my current code in question.
#Bean
public DaoAuthenticationProvider authProvider() {
// LimitLoginAuthenticationProvider is my own class which extends DaoAuthenticationProvider
final DaoAuthenticationProvider authProvider = new LimitLoginAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
** and change this method code**
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider())
.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

Categories