Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security multiple successful authentication providers

I want users of my web application to be authenticated by LDAP AND additional custom authentication. It's a Spring Boot application written in Kotlin. I have configured the AuthenticationManagerBuilder as follows

@Autowired
lateinit var authenticationProvider: CustomAuthenticationProvider

override fun configure(auth: AuthenticationManagerBuilder) {
    auth
            .authenticationProvider(authenticationProvider)

    auth
            .ldapAuthentication()
                .userDnPatterns("uid={0},ou=people")
                .groupSearchBase("ou=groups")
                .contextSource()
                .url("ldap://localhost:8389/dc=example,dc=com")
            .and()
                .passwordCompare()
                .passwordEncoder(PlaintextPasswordEncoder())
                .passwordAttribute("userPassword")
}

I want to chain the authentication so that if the CustomAuthenticationProvider successfully authenticates (function authenticate does not throw) authentication continues using the LDAP authentication provider.

As written if the CustomAuthenticationProvider successfully authenticates then LDAP authentication (and any subsequent authentication provider) is not evaluated. Only if the CustomAuthenticationProvider throws is LDAP authentication performed.

I have read a number of articles (for example Multiple Authentication Providers in Spring Security) which detail having multiple authentication providers but with OR behaviour rather than AND behaviour. Any suggestions?


1 Answers

Maybe I have some. But let's analyse what is going on under the hood before.

The default authentication manager implementation in Spring Security (ProviderManager) maintains a list of authentication providers and the first one that performs successful authentication stops the chain - the rest are not called. I'm sure that you cannot change that. When you use the AuthenticationManagerBuilder you add authentication providers in the ProviderManager.

A high level overview of what is going on is shown on the image below:

Security architecture

In the source code this looks like this (details skipped for brevity):

public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        Class<? extends Authentication> toTest = authentication.getClass();
        ...
        for (AuthenticationProvider provider : getProviders()) {
            if (!provider.supports(toTest)) {
                continue;
            }

            try {
                result = provider.authenticate(authentication);

                if (result != null) {
          ...
                    break;
                }
            }
      ...
            catch (AuthenticationException e) {
                lastException = e;
            }
        }

        if (result != null) {
            ...
            return result;
        }
  }

So what could you do... hm. First the questions of @dur are valid :-) Second - it is obvious that you cannot do what you want to with the standard authentication manager which makes sense to me.

What I think is that you may try two things if you still want to go that way:

  1. Provide your own authentication manager implementation in your filter chain. This seems a bit challenging to me.
  2. Make sure that your custom authentication provider handles all necessary authentication actions.
like image 195
Lachezar Balev Avatar answered Oct 22 '25 01:10

Lachezar Balev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!