Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security Custom Authentication - AuthenticationProvider vs UserDetailsService

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?

like image 249
Evgeni Dimitrov Avatar asked Jul 25 '15 20:07

Evgeni Dimitrov


People also ask

Which authentication is best in spring boot?

You can use custom token based implementation, you can create a custom token that you can store in DB but JWT is a good choice.

What is difference between AuthenticationManager and AuthenticationProvider?

Authentication Provider calls User Details service loads the User Details and returns the Authenticated Principal. Authentication Manager returns the Authenticated Object to Authentication Filter and Authentication Filter sets the Authentication object in Security Context .

What is the use of UserDetailsService in Spring Security?

The UserDetailsService interface is used to retrieve user-related data. It has one method named loadUserByUsername() which can be overridden to customize the process of finding the user. It is used by the DaoAuthenticationProvider to load details about the user during authentication.


2 Answers

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.

like image 96
Hossein Avatar answered Oct 18 '22 20:10

Hossein


From spring security documention, https://docs.spring.io/spring-security/site/docs/5.0.0.RC1/reference/htmlsingle/#overall-architecture

There is often some confusion about UserDetailsService. It is purely a DAO for user data and performs no other function other than to supply that data to other components within the framework. In particular, it does not authenticate the user, which is done by the AuthenticationManager. In many cases it makes more sense to implement AuthenticationProvider directly if you require a custom authentication process.

AuthenticationProvider and UserDetailsService have different purpose.

AuthenticationProvider authenticates(compares) the user(request) provided username and password against system User(This can be any system like DB which maintains list of registered users)

It is the responsiblity of UserDetailsService Implementation to get the System User Details that match with user provided Username. Here it just gets the users that have same username and does not tell the application whether authentication is successful or failed.

Example : Spring provides the following as a default setup to authenticate a user details against database

  • AuthenticationProvider - DaoAuthenticationProvider which extends AbstractUserDetailsAuthenticationProvider that calls the authenticate method by passing on username, Authentication object
  • UserDetailsService - JdbcDaoImpl
  • Flow of authentication
  1. DaoAuthenticationProvider responsibility is to authenticate the username and password obtained from request with Database user.
  2. To get the corresponding Database User, it asks UserDetailsService Implementataion JdbcDaoImpl to get a UserDetail object from database with name same as request username.Here JdbcDaoImpl just fetches the UserDetails object from system.It will either send back the user found in DB or send an exception that user is not found.
  3. If user details are found in DB, DaoAuthenticationProvider then proceeds with checking on request user password with DB found user password else fails the authentication.
  4. DaoAuthenticationProvider will respond whether the user is authenticated or not based on JdbcDaoImpl response.

Have a look here to understand it better:

AuthenticationProvider - DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider

UserDetailsService - JdbcDaoImpl

UserDetails - User

like image 25
Gautam Tadigoppula Avatar answered Oct 18 '22 20:10

Gautam Tadigoppula