2727import org .springframework .context .ApplicationEventPublisher ;
2828import org .springframework .security .core .GrantedAuthority ;
2929import org .springframework .security .core .authority .SimpleGrantedAuthority ;
30+ import org .springframework .security .authentication .event .InteractiveAuthenticationSuccessEvent ;
31+ import org .springframework .security .core .Authentication ;
3032import org .springframework .security .core .context .SecurityContext ;
3133import org .springframework .security .core .context .SecurityContextHolder ;
3234import org .springframework .security .core .session .SessionInformation ;
@@ -477,6 +479,18 @@ void authWithoutPassword_authenticatesValidUser() {
477479 SecurityContext securityContext = mock (SecurityContext .class );
478480 mockedSecurityHolder .when (SecurityContextHolder ::getContext ).thenReturn (securityContext );
479481
482+ // Capture the authentication set on the context and return it on getAuthentication()
483+ ArgumentCaptor <Authentication > authCaptor = ArgumentCaptor .forClass (Authentication .class );
484+
485+ // Use thenAnswer to capture and store the authentication set
486+ final Authentication [] storedAuth = new Authentication [1 ];
487+ org .mockito .Mockito .doAnswer (invocation -> {
488+ storedAuth [0 ] = invocation .getArgument (0 );
489+ return null ;
490+ }).when (securityContext ).setAuthentication (any ());
491+
492+ when (securityContext .getAuthentication ()).thenAnswer (invocation -> storedAuth [0 ]);
493+
480494 // When
481495 userService .authWithoutPassword (testUser );
482496
@@ -488,6 +502,53 @@ void authWithoutPassword_authenticatesValidUser() {
488502 }
489503 }
490504
505+ @ Test
506+ @ DisplayName ("authWithoutPassword - publishes InteractiveAuthenticationSuccessEvent" )
507+ void shouldPublishInteractiveAuthenticationSuccessEventWhenAuthSucceeds () {
508+ // Given
509+ DSUserDetails userDetails = new DSUserDetails (testUser );
510+ Collection <? extends GrantedAuthority > authorities = Arrays .asList (new SimpleGrantedAuthority ("ROLE_USER" ));
511+
512+ when (dsUserDetailsService .loadUserByUsername (testUser .getEmail ())).thenReturn (userDetails );
513+ when (authorityService .getAuthoritiesFromUser (testUser )).thenReturn ((Collection ) authorities );
514+
515+ HttpServletRequest mockRequest = mock (HttpServletRequest .class );
516+ HttpSession mockSession = mock (HttpSession .class );
517+ ServletRequestAttributes attrs = mock (ServletRequestAttributes .class );
518+
519+ when (attrs .getRequest ()).thenReturn (mockRequest );
520+ when (mockRequest .getSession (true )).thenReturn (mockSession );
521+
522+ try (MockedStatic <RequestContextHolder > mockedHolder = mockStatic (RequestContextHolder .class );
523+ MockedStatic <SecurityContextHolder > mockedSecurityHolder = mockStatic (
524+ SecurityContextHolder .class )) {
525+
526+ mockedHolder .when (RequestContextHolder ::getRequestAttributes ).thenReturn (attrs );
527+ SecurityContext securityContext = mock (SecurityContext .class );
528+ mockedSecurityHolder .when (SecurityContextHolder ::getContext ).thenReturn (securityContext );
529+
530+ // Return the authentication that was set
531+ final Authentication [] storedAuth = new Authentication [1 ];
532+ org .mockito .Mockito .doAnswer (invocation -> {
533+ storedAuth [0 ] = invocation .getArgument (0 );
534+ return null ;
535+ }).when (securityContext ).setAuthentication (any ());
536+ when (securityContext .getAuthentication ()).thenAnswer (invocation -> storedAuth [0 ]);
537+
538+ // When
539+ userService .authWithoutPassword (testUser );
540+
541+ // Then
542+ ArgumentCaptor <InteractiveAuthenticationSuccessEvent > eventCaptor =
543+ ArgumentCaptor .forClass (InteractiveAuthenticationSuccessEvent .class );
544+ verify (eventPublisher ).publishEvent (eventCaptor .capture ());
545+
546+ InteractiveAuthenticationSuccessEvent event = eventCaptor .getValue ();
547+ assertThat (event ).isNotNull ();
548+ assertThat (event .getAuthentication ().getPrincipal ()).isEqualTo (userDetails );
549+ }
550+ }
551+
491552 @ Test
492553 @ DisplayName ("authWithoutPassword - handles null user" )
493554 void authWithoutPassword_handlesNullUser () {
@@ -497,6 +558,7 @@ void authWithoutPassword_handlesNullUser() {
497558 // Then
498559 verify (dsUserDetailsService , never ()).loadUserByUsername (any ());
499560 verify (authorityService , never ()).getAuthoritiesFromUser (any ());
561+ verify (eventPublisher , never ()).publishEvent (any ());
500562 }
501563
502564 @ Test
@@ -511,6 +573,7 @@ void authWithoutPassword_handlesUserWithNullEmail() {
511573 // Then
512574 verify (dsUserDetailsService , never ()).loadUserByUsername (any ());
513575 verify (authorityService , never ()).getAuthoritiesFromUser (any ());
576+ verify (eventPublisher , never ()).publishEvent (any ());
514577 }
515578
516579 @ Test
@@ -525,6 +588,7 @@ void authWithoutPassword_handlesUserNotFound() {
525588
526589 // Then
527590 verify (authorityService , never ()).getAuthoritiesFromUser (any ());
591+ verify (eventPublisher , never ()).publishEvent (any ());
528592 }
529593
530594 @ Test
0 commit comments