AuthenticationSuccessEvent seems to be fired multiple times for single requests. Not sure if this is expected behavior or not, I will try to create a stripped down app to demonstrate. I just wanted to make sure that this wouldn't be intended behavior. Code configuration is below in Kotlin:

@EnableWebSecurity
class WebSecurityConfiguration: WebSecurityConfigurerAdapter() {
    /**
     * Spring Authentication Manager
     */
    @Bean
    override fun authenticationManager(): AuthenticationManager {
        return super.authenticationManager()
    }
}

@Configuration
@EnableResourceServer
@EnableWebSecurity
@Order(-1)
class ResourceServerConfig(private val authenticationProvider: MongoDBAuthenticationProvider) : ResourceServerConfigurerAdapter() {
    // Constants
    private val antPatternsForAllUsers = arrayOf("/actuator/**")

    @Autowired
    fun configureGlobal(auth: AuthenticationManagerBuilder) {
        auth.authenticationProvider(authenticationProvider)
    }

    override fun configure(http: HttpSecurity) {
        http
                .addFilterBefore(CorsFilter(), SessionManagementFilter::class.java)
                .authorizeRequests().antMatchers(*antPatternsForAllUsers).permitAll().and()
                .authorizeRequests().anyRequest().authenticated().and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .csrf().disable()
    }
}



@Component
class AuthListener {

    @EventListener
    fun authenticationFailed(event: OAuth2AuthenticationFailureEvent) {
        System.out.println("OAuth2AuthenticationFailureEvent")
    }

    @EventListener
    fun authenticationSucceeded(event: AuthenticationSuccessEvent) {
        System.out.println("AuthenticationSuccessEvent " + event.toString())
    }

    @EventListener fun authenticationFailed(event: AuthenticationFailureBadCredentialsEvent) {
        System.out.println("AuthenticationFailureBadCredentialsEvent " + event.toString())
    }
}

Comment From: jzheaux

Hey, @kibbled! Thanks for the report. It's a little confusing, but would you please report this ticket in https://github.com/spring-projects/spring-security-oauth2-boot? Thank you!

Comment From: tadaskay

I am also observing the same issue with 5.1.x, had to downgrade security-config and security-core to 5.0.9 temporarily. For one BadCredentialsException, there are 2 events published of the same type.

Comment From: jzheaux

@tadaskay is this the issue you are experiencing? https://github.com/spring-projects/spring-security/issues/6281

Comment From: tadaskay

@jzheaux Yes, thank you!

Comment From: jzheaux

Closing this. If the problem persists, please post to https://github.com/spring-projects/spring-security-oauth2-boot/issues

Comment From: zgarcia83

I had the "same issue" but then I realized that the AuthenticationSuccessEvent is called twice as in OAuth2 the client (Application) have to do authentication as well.

I implemented the logic to determine whether the AuthenticationSuccessEvent is called for the client or application user.

Comment From: eranf91

I know that this issue is closed but it seems to be relevant for the latest version of spring security at the moment. I think that the events should be separated.

Comment From: jzheaux

@eranf91 can you clarify what you are wanting to see changed? It might be good for you to open a separate ticket and flesh out a bit more what you mean by:

I think that the events should be separated

Comment From: amirensit

Sorry for commenting on closed issue But I have a solution that worked for me. ( Using the debugging mode ):

  • For the Client authentication: authenticationSuccessEvent.getSource() is an instance of OAuth2Authentication.

  • For the User authentication: authenticationSuccessEvent.getSource() is an instance of UsernamePasswordAuthenticationToken.

So to execute logic only after user authentication :

@Component
public class AuthenticationSuccessEventListener implements ApplicationListener<AuthenticationSuccessEvent> {

   @Override
   public void onApplicationEvent(AuthenticationSuccessEvent authenticationSuccessEvent) {
       if (authenticationSuccessEvent.getSource() instanceof UsernamePasswordAuthenticationToken) {
               // the logic here
       }
   }
}

I hope It helps.

Comment From: isscy

@amirensit Client authentication also source instance of UsernamePasswordAuthenticationToken ! In the ClientCredentialsTokenEndpointFilter.attemptAuthentication or BasicAuthenticationFilter.doFilterInternal , convert clientid, clientSecret from request to UsernamePasswordAuthenticationToken