question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Subclasses of AbstractAuthenticationEvent are not fired anymore

See original GitHub issue

Given the following application

import java.security.Principal;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@Configuration
@RestController
public class AuthlistenerApplication {

    @GetMapping("/")
    public String hello(final Principal principal) {
        return "Hello, " + principal.getName() + ".";
    }

    @Bean
    public ApplicationListener<AuthenticationSuccessEvent> onSuccessListener() {
        return (AuthenticationSuccessEvent event) -> {
            System.out.println("Yeah!");
        };
    }

    @Bean
    public ApplicationListener<AuthenticationFailureBadCredentialsEvent> onBadCredentialsListener() {
        return (AuthenticationFailureBadCredentialsEvent event) -> {
            System.out.println("Oh no...");
        };
    }

    public static void main(String[] args) {
        SpringApplication.run(AuthlistenerApplication.class, args);
    }
}

Running this on Spring Boot 1.5.9.RELEASE triggers either AuthenticationSuccessEvent or an AuthenticationFailureBadCredentialsEvent event, depending if one uses the correct password.

Neither of those events are triggered on 2.0.0.BUILD-SNAPSHOT and probably not on the Milestone as well. Here’s a test to confirm this:

import java.util.Base64;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@TestPropertySource(properties = {
    "security.user.name = testuser",
    "security.user.password = testpassword",
    "spring.security.user.name = testuser",
    "spring.security.user.password = testpassword",})
public class AuthlistenerApplicationTests {

    @Rule
    public OutputCapture output = new OutputCapture();

    @Autowired
    TestRestTemplate restTemplate;

    @Test
    public void logsSuccess() throws Exception {
        final HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Basic " + Base64.getEncoder().encodeToString("testuser:testpassword".getBytes()));
        headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);

        final ResponseEntity<String> r = restTemplate
                .exchange("/", HttpMethod.GET, new HttpEntity<>(headers), String.class);
        assertThat(r.getStatusCode(), is(equalTo(HttpStatus.OK)));
        assertThat(r.getBody(), is(equalTo("Hello, testuser.")));
        assertThat("Output did not contain 'Yeah!'", output.toString(), containsString("Yeah!"));
    }

    @Test
    public void logsFailure() throws Exception {
        final HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Basic " + Base64.getEncoder().encodeToString("testuser:fump".getBytes()));
        headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);

        final ResponseEntity<String> r = restTemplate
                .exchange("/", HttpMethod.GET, new HttpEntity<>(headers), String.class);        
        assertThat(r.getStatusCode(), is(equalTo(HttpStatus.UNAUTHORIZED)));
        assertThat("Output did not contain 'Oh no...'", output.toString(), containsString("Oh no..."));        
    }
}

I used the snapshot for the test as the test makes use of the new old properties to configure the user (see #10963).

I already checked if the DefaultAuthenticationEventPublisher is still part of SecurityAutoConfiguration and yes, it is. So I assume that those events should still be published.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:15 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
mbhavecommented, Jan 2, 2018

@michael-simons Spring Security will provide a hook to register a bean of type AuthenticationEventPublisher. If it finds a bean of that type, it will use that as the default publisher. This is consistent with the approach of registering a UserDetailsService bean (or PasswordEncoder, AuthenticationProvider), which gets picked up by Spring Security.

0reactions
marccollincommented, Jan 16, 2018

@mctdi remove extends WebSecurityConfigurerAdapter in your MultiHttpSecurityConfig class and copy your protected void configure(AuthenticationManagerBuilder auth) implementation in RestWebSecurityConfigurationAdapter and FormLoginWebSecurityConfigurerAdapter

Read more comments on GitHub >

github_iconTop Results From Across the Web

spring - @EventListener for AuthenticationSuccessEvent or ...
When I authenticate correctly in the application, no event is released by Spring Security and therefore this Event Listener is not called.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found