Reputation: 545
Right now my authentication is done with username and password. I'd like to add one more step to it so that it checks if user is activated or not. I have a user table that holds the value if the user has activated the account.
I have my SecurityConfig.java
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// This somehow works but only if the account is not validated
// auth.authenticationProvider(new UserActivatedAuthenticationProvider(userService));
auth.userDetailsService(userDetailsService).passwordEncoder(new ShaPasswordEncoder(encodingStrength));
}
And UserActivatedAuthenticationProvider.java
@Component
public class UserActivatedAuthenticationProvider implements AuthenticationProvider {
private final UserService userService;
@Autowired public UserActivatedAuthenticationProvider(UserService userService) {
this.userService = userService;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String name = authentication.getName();
User user = userService.findByEmail(name);
if (user != null) {
if (!user.isActivated()) {
throw new BadCredentialsException(name + " email is not activated.");
}
}
Object credentials = authentication.getCredentials();
if (!(credentials instanceof String)) {
return null;
}
String password = credentials.toString();
Authentication auth = new UsernamePasswordAuthenticationToken(name, password);
return auth;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
I want to proceed with authentication only if the account is activated. I can't use userService
in AuthenticationManagerBuilder
because I can't get the username. I am using this project as a seed. In short... I also want to check the value of is_activated
column and proceed based on that value as it now does (username and password validation).
Upvotes: 0
Views: 1762
Reputation: 21883
You don't need an AuthenticationProvider
. You need to implement the UserDetailsService
as following;
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userService.findByEmail(username);
if(user == null) {
throw new UsernameNotFoundException(username);
}
return org.springframework.security.core.userdetails.User(username, user.getPassword(), user.isActivated(), true, true, true, user.getRoles().stream().map(role -> role.getRoleName()).map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
}
}
The spring class org.springframework.security.core.userdetails.User
as an property named enabled
for which you can pass your user.isActivated()
flag from database.
Upvotes: 1
Reputation: 11659
You can do that by providing your custom user details service.
@Autowired
private CustomUserDetailsService customUserDetailsService ;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService ).passwordEncoder(new ShaPasswordEncoder(encodingStrength));
}
and
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userService.findByEmail(username);
if(user == null) {
throw new UsernameNotFoundException(username);
}
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("USER");
authorities.add(grantedAuthority);
return org.springframework.security.core.userdetails.User(username, user.getPassword(), user.isActivated(), true, true, true, authorities );
}
}
Now based on Boolean value of third param, spring security will auto allow/deny user login and will also give the message "User disabled" if user is not activated.
Upvotes: 1