Java – Spring Security Custom Authentication – AuthenticationProvider vs UserDetailsService

javaspringspring-mvcspring-security

As far as I can understand when you want custom authentication in Spring Security you can either implement a custom AuthenticationProvider or custom UserDetailsService.

@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth    
            //.authenticationProvider(authProvider)  // option 1
            .userDetailsService(userDetailsService); // option 2

    }

In the AuthenticationProvider you can check the username and password and return Authentication with your custom object in it.

public Authentication authenticate(Authentication authentication){
        if (checkUsernameAndPassword(authentication)) {
            CustomUserDetails userDetails = new CustomUserDetails();
            //add whatever you want to the custom user details object
            return new UsernamePasswordAuthenticationToken(userDetails, password, grantedAuths);
        } else {
            throw new BadCredentialsException("Unable to auth against third party systems");
        }
    }

In the UserDetailsService you get only the username and when you return the custom UserDeatails, the framework performs a check on the password.

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        CustomUserDetails user = new CustomUserDetails();
        //add whatever you want to the custom user details object
        return user;
    }

Looks like both can produce similar results. So the question is what is the difference? When to user one vs the other?

Best Answer

The answer is inside your question. when you are using a different authentication system, and the password is not provided in your own database/data model, you have to use the AuthenticationProvider. for example, I've worked in a project that the customer had a centralized authentication system (CAS), so my system had no idea about the password, I had to implement the AuthenticationProvider and send the given password to the CAS, and act according to its answer.

But in another system, I was storing the password in my database, so all I had to do was implementing the UserDetailsService and check if the user exists in my database or not, spring-security had to do the rest.

Related Topic