Reputation: 1047
I writing app where user logs in using facebook.
My security config/application class:
@SpringBootApplication
@EnableOAuth2Sso
@ComponentScan(basePackages = { "app" })
public class Application extends WebSecurityConfigurerAdapter {
@SuppressWarnings("SpringJavaAutowiringInspection")
@Autowired
private OAuth2ClientContext oauth2ClientContext;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/",
"/login**",
"/webjars/**",
"/bower_components/**",
"/assets/**",
"/app/**",
"/api/auth/isAuthenticated")
.permitAll()
.anyRequest()
.authenticated()
.and().formLogin().defaultSuccessUrl("/", true).loginPage("/login").permitAll()
.and().logout().logoutSuccessUrl("/").permitAll()
.and().addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
}
@Bean
@ConfigurationProperties("facebook")
ClientResources facebook() {
return new ClientResources();
}
private Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<>();
filters.add(ssoFilter(facebook(), "/login/facebook"));
filter.setFilters(filters);
return filter;
}
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
OAuth2RestTemplate facebookTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
filter.setRestTemplate(facebookTemplate);
filter.setTokenServices(new UserInfoTokenServices(client.getResource().getUserInfoUri(), client.getClient().getClientId()));
return filter;
}
class ClientResources {
private OAuth2ProtectedResourceDetails client = new AuthorizationCodeResourceDetails();
private ResourceServerProperties resource = new ResourceServerProperties();
public OAuth2ProtectedResourceDetails getClient() {
return client;
}
public ResourceServerProperties getResource() {
return resource;
}
}
My problem is that even that I configured listener:
package app;
@Component
public class AuthenticationListener implements ApplicationListener<AuthenticationSuccessEvent> {
@Override
public void onApplicationEvent(AuthenticationSuccessEvent event) {
System.out.println("Event fired");
}
}
it is never fired. I tried solution provided here : Spring boot OAuth successful login listener not triggering but it does not help either. SecurityContextHolder.getContext().getAuthentication().isAuthenticated()
returns true after logging in.
Upvotes: 1
Views: 1629
Reputation: 1027
To publish authentication events it's possible to override authenticationHandler's.
basic security config:
@EnableWebFluxSecurity
public class SecurityConfig {
@Autowired
public ApplicationEventPublisher applicationEventPublisher;
@Bean
public AuthenticationEventPublisher authenticationEventPublisher() {
return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
}
@Bean
public ServerAuthenticationEntryPoint serverAuthenticationEntryPoint() {
return new HttpBasicServerAuthenticationEntryPoint();
}
@Bean
public LoggerListener loggerListener() {
return new LoggerListener();
}
@Bean
public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange()
.anyExchange().authenticated()
.and()
.formLogin(login -> {
login.authenticationSuccessHandler(new LoggingAuthenticationSuccessHandler());
login.authenticationFailureHandler(new LoggingAuthenticaionFailedHandler(serverAuthenticationEntryPoint()));
})
.build();
}
}
success handler:
class LoggingAuthenticationSuccessHandler extends WebFilterChainServerAuthenticationSuccessHandler {
@Autowired
private AuthenticationEventPublisher eventPublisher;
@Override
public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
this.eventPublisher.publishAuthenticationSuccess(authentication);
return super.onAuthenticationSuccess(webFilterExchange,authentication);
}
}
failure handler:
class LoggingAuthenticaionFailureHandler extends ServerAuthenticationEntryPointFailureHandler {
@Autowired
private AuthenticationEventPublisher eventPublisher;
public LoggingAuthenticaionFailureHandler(ServerAuthenticationEntryPoint authenticationEntryPoint) {
super(authenticationEntryPoint);
}
@Override
public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception) {
AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", "anonymousUser",
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
this.eventPublisher.publishAuthenticationFailure(exception, token);
return super.onAuthenticationFailure(webFilterExchange, exception);
}
}
and event listener:
public class AuthenticationEvents {
private LoggerListener loggerListener;
@Autowired
public AuthenticationEvents(LoggerListener logger) {
this.loggerListener = logger;
}
@EventListener
public void onSuccess(InteractiveAuthenticationSuccessEvent success) {
loggerListener.onApplicationEvent(success);
}
@EventListener
public void onSuccess(AuthenticationSuccessEvent success) {
loggerListener.onApplicationEvent(success);
}
@EventListener
public void onFailure(AbstractAuthenticationFailureEvent failures) {
loggerListener.onApplicationEvent(failures);
}
}
The standard LoggerListener could be replaced with own implementation. Keep in mind, if Your security filter chain has UsernamePasswordAuthenticationFilter then overrides the success handler is not necessary.
Upvotes: 0
Reputation: 33121
OAuth SSO support does not fire AuthenticationSuccessEvent
indeed. This is something I've been facing recently as well. This is implemented now but not released yet.
Upvotes: 2