diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/security/AuthenticationAuditListener.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/security/AuthenticationAuditListener.java index 87ff5f6fb0..4f85b86701 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/security/AuthenticationAuditListener.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/security/AuthenticationAuditListener.java @@ -61,6 +61,9 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList Map data = new HashMap(); data.put("type", event.getException().getClass().getName()); data.put("message", event.getException().getMessage()); + if (event.getAuthentication().getDetails() != null) { + data.put("details", event.getAuthentication().getDetails()); + } publish(new AuditEvent(event.getAuthentication().getName(), "AUTHENTICATION_FAILURE", data)); } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/security/AuthenticationAuditListenerTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/security/AuthenticationAuditListenerTests.java index aca33b1803..59823e51a3 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/security/AuthenticationAuditListenerTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/security/AuthenticationAuditListenerTests.java @@ -16,9 +16,13 @@ package org.springframework.boot.actuate.security; +import java.util.Map; + import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.springframework.boot.actuate.audit.listener.AuditApplicationEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.authentication.BadCredentialsException; @@ -30,6 +34,8 @@ import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; import org.springframework.security.web.authentication.switchuser.AuthenticationSwitchUserEvent; +import static org.hamcrest.Matchers.hasEntry; +import static org.junit.Assert.assertThat; import static org.mockito.Matchers.anyObject; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -82,4 +88,32 @@ public class AuthenticationAuditListenerTests { verify(this.publisher).publishEvent((ApplicationEvent) anyObject()); } + @Test + public void shouldPassDetailsToAuditEventOnAuthenticationFailureEvent() + throws Exception { + // given + final Object details = new Object(); + final AuthenticationFailureExpiredEvent event = + createAuthenticationFailureEvent(details); + + // when + this.listener.onApplicationEvent(event); + + // then + final ArgumentCaptor applicationEventArgumentCaptor = + ArgumentCaptor.forClass(AuditApplicationEvent.class); + verify(this.publisher).publishEvent(applicationEventArgumentCaptor.capture()); + final Map eventData = + applicationEventArgumentCaptor.getValue().getAuditEvent().getData(); + assertThat(eventData, hasEntry("details", details)); + } + + private AuthenticationFailureExpiredEvent createAuthenticationFailureEvent( + final Object details) { + final UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken("user", "password"); + authentication.setDetails(details); + final BadCredentialsException exception = new BadCredentialsException("Bad user"); + return new AuthenticationFailureExpiredEvent(authentication, exception); + } }