Home » Framework » How to do multiple Authentication in Spring Security

How to do multiple Authentication in Spring Security

In this article, we are going to see how to do Authentication if the application is having multiple types of login. The login type may be form login, Oauth, SSO/LDAP, or Octa.

In the last article, we discussed how to do authentication when an application is having a single type of login method. if you want to know that please click here Spring Security Authentication Flow.

But here let see how to configure authentication if the application deals with multiple types of login. In the last article, we configured AuthenticationProvider interface with configure method to deal with form login authentication.

Configuration of AuthenticationProvider in Spring Security

AuthenticationProvider is responsible for doing authentication. Here for handling multiple types of login, we have to configure multiple AuthenticationProvider in an application.

For example, let's consider the application is having form login (username, password), Oauth, and LDAP types of login. Then we have to configure AuthenticationProvider for every type of login to do the particular type of authentication.

Each AuthenticationProvider is responsible for any one of the login type which we configured in an application. The below diagram shows how the AuthenticationProvider configures with every login type.

Authentication-Providers
Authentication-Providers

In the above diagram, we configured individual AuthenticationProvider for username and password, Oauth, LDAP types of authentication. Every authentication providers do the authentication based on the configuration.

Now the question will come how the application knows which type of authentication request is this? and which provider is going to handle it?. Right!. For handling this we have to coordinate all the AuthenticationProviders each other. Let see how to do it.

Configuration of AuthenticationManager in Spring Security

There is a manager called AuthenticationManager which coordinates all the AuthenticationProviders to handle different types of authentication requests.

Let me give a small example for this AuthenticationManager then you can easily know the purpose of it. Let say in a start-up company there are some 20 employees. There are 4 groups and each group is having 5 employees and every group is having one team leader to handle the remaining 4.

These team leaders co-ordinate all the group of employees and do the work. Right!. But there is a situation we have to co-ordinate all the team leaders to know the team performance. In this scenario, a company assigns a manager to coordinate all the team leaders.

Like the same way, each AuthenticationProvider does its authentication based on the configuration. But we have to redirect the login request to that particular AuthenticationProvider. For that first, we have to coordinate all the providers by implementing the manager called AuthenticationManager.

There are many ways to configure AuthenticationManager. But the famous one is ProviderManager implementation. We have to configure the ProviderManager interface which implements AuthenticaitonManager.

Let me explain how it works. This ProviderManager receives the login request and passes that to AuthenticationManager to handle it. This AuthenticationManager asks all the AuthenticationProvider to support this type of authentication or not.

If any of the AuthenticationProvider supports this login type then the request will move to that particular provider to authenticate it. Every AuthenticationProvider is having a method called supports() which checks that whether this provider supports this type of authentication or not.

Method Summary of Authentication Provider Interface

Modifier and TypeMethod and Description
Authenticationauthenticate(Authentication authentication)
Performs authentication with the same contract
as AuthenticationManager.authenticate(Authentication).
booleansupports(Class<?> authentication)
Returns true if this AuthenticationProvider supports
the indicated Authentication Object.

This AuthenticationManager takes the input as an Authentication object and the output also the same Authentication object. The below diagram shows how the request goes from manager to provider.

Provider-Manager-Security
Provider-Manager

Cool!. up to this, we have seen how the authentication works if the application is having multiple types of authentication. Now we are going to see how the authentication exactly works.

We saw that the authenticate() method of AuthenticationProvider actually does the authentication right. But here let me explain how it happens.

There are several types of authentication strategies in an application. Based on that the logic differs to authenticate the users. Here let me take the username and password type of login and explain how the authentication takes place.

There is a service called UserDetailsService in which the method called loadUserByUserName() in Spring Security which is responsible for checking whether the username found in the database or not.

This method returns the User object which has the information of user once the username is found in the database. The authenticate() method calls this method loadUserByUserName() to check whether the user credentials are valid or not for the type of form login.

Method Summary of UserDetails service

Modifier and TypeMethod and Description
Collection<GrantedAuthority>getAuthorities()
Returns the authorities granted to the user.
StringgetPassword()
Returns the password used to authenticate the user.
StringgetUsername()
Returns the username used to authenticate the user.
booleanisAccountNonExpired()
Indicates whether the user's account has expired.
booleanisAccountNonLocked()
Indicates whether the user is locked or unlocked.
booleanisCredentialsNonExpired()
Indicates whether the user's credentials (password) has expired.
booleanisEnabled()
Indicates whether the user is enabled or disabled

Multiple Authentication Flow in Spring Security

The below diagram shows the flow of authentication from start to end.

Spring-Security-Multiple-Authentication
Spring-Security-Multiple-Authentication
  1. Login request reaches the filter and the filter receives the credentials from the request and puts that into the Authentication object and passes that to AuthenticationManager.
  2. AuthenticationManager asks all the AuthenticationProviders to support this type of authentication or not. Once it identified the right provider then the Authentication object passes to that particular provider.
  3. The AuthenticationProvider holds the Authentication object and validates that through its validate method(). This validate method calls the corresponding authentication logic to authenticate the users.
  4. Once the user is authenticated successfully the Authentication object returns from the provider to the manager then the manager to filter. This object holds the information of the validated user, not the credentials.

That's it. This is what authentication works in Spring Security if the application is having multiple types of authentication.

Now we all are having the question of whether the subsequent request needs authentication or not in Spring Security. Really not needed once the user is authenticated then the subsequent request from the same user does not need authentication.

Now we have the question like how the application framework knows whether this user authenticated already or not. Yes, Spring Security can handle this.

Actually, filters can do this. Filter saves the authenticated principal in Thread Local and assigns that with the session. This session remembers who the logged-in user is and whether the user is already logged in or not.

Filters are responsible for taking the context of the session and saving it in the thread-local again and it is available for the entire framework. This is why every subsequent request doesn't need authentication.

Hope you understood how the authentication works with the multiple types of login in Spring Security. In the next article, we will see how to do authentication with the users from the database. Thanks!. Keep Reading!.

4 thoughts on “How to do multiple Authentication in Spring Security

  1. I have two authentication providers TokenAuthProvider and BasicAuthProvider, I want one two be used for a specific URL and another to be used for the rest of the URLs. How can I configure my HttpSecurity to achieve this in

    1. You have to configure multiple WebSecurityConfigurerAdapter with configure method which takes HttpSecurity as an argument. In that configure method you have to configure the authentication type with the URL's. Please see the below code. Some URL's authenticated by JWT token authentication and others by basic authentication.

      Public class SecurityConfig {
      @Order(1)
      @Configuration
      public static class JWTTokenAuthConfig extends WebSecurityConfigurerAdapter {
      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http
      .antMatcher("/mobapi/**")
      .cors()
      .and()
      .csrf()
      .disable() // we don't need CSRF because our token is invulnerable
      .authorizeRequests()
      .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
      .antMatchers(RESET_PASSWORD_URL).permitAll()
      .anyRequest().authenticated()
      .and()
      .addFilter(new JWTAuthenticationFilter(authenticationManager()))
      .addFilter(new JWTAuthorizationFilter(authenticationManager()))
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
      }

      }

      @Order(2)
      @Configuration
      public static class BasicAuthConfig extends WebSecurityConfigurerAdapter {
      @Autowired
      AuthenticationEntryPoint authenticationEntryPoint;

      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http
      .antMatcher("/webapi/**")
      .csrf().disable()
      .authorizeRequests()
      .anyRequest().authenticated()
      .and()
      .httpBasic()
      .authenticationEntryPoint(authenticationEntryPoint)
      .and()
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      ;
      }
      }
      }
      }

Leave a Reply

Your email address will not be published. Required fields are marked *