Phaze
Phaze

Reputation: 545

Adding a custom filter to authentication process in Spring Security

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

Answers (2)

shazin
shazin

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

tryingToLearn
tryingToLearn

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

Related Questions