Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
Expand All @@ -43,7 +42,6 @@
import com.vaadin.flow.spring.flowsecurity.data.UserInfo;
import com.vaadin.flow.spring.flowsecurity.service.UserInfoService;
import com.vaadin.flow.spring.flowsecurity.views.LoginView;
import com.vaadin.flow.spring.security.VaadinAwareSecurityContextHolderStrategyConfiguration;

import static com.vaadin.flow.spring.flowsecurity.service.UserInfoService.ROLE_ADMIN;
import static com.vaadin.flow.spring.security.VaadinSecurityConfigurer.vaadin;
Expand All @@ -52,7 +50,6 @@
@EnableMethodSecurity(prePostEnabled = false, jsr250Enabled = true, securedEnabled = true)
@Configuration
@Profile("default")
@Import(VaadinAwareSecurityContextHolderStrategyConfiguration.class)
public class SecurityConfig {

private final UserInfoService userInfoService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
Expand All @@ -41,14 +40,12 @@
import com.vaadin.flow.spring.flowsecurity.service.UserInfoService;
import com.vaadin.flow.spring.flowsecurity.views.LoginView;
import com.vaadin.flow.spring.security.NavigationAccessControlConfigurer;
import com.vaadin.flow.spring.security.VaadinAwareSecurityContextHolderStrategyConfiguration;

import static com.vaadin.flow.spring.flowsecurity.service.UserInfoService.ROLE_ADMIN;
import static com.vaadin.flow.spring.security.VaadinSecurityConfigurer.vaadin;

@EnableWebSecurity
@Configuration
@Import(VaadinAwareSecurityContextHolderStrategyConfiguration.class)
public class SecurityConfig {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
Expand Down Expand Up @@ -70,11 +71,12 @@ public class SecurityConfig {
@Autowired
private RequestUtil requestUtil;

private final AuthenticationContext authenticationContext = new AuthenticationContext();
@Autowired
private SecurityContextHolderStrategy securityContextHolderStrategy;

@Bean
public AuthenticationContext authenticationContext() {
return authenticationContext;
return new AuthenticationContext(securityContextHolderStrategy);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,6 @@ public void navigate_in_thread_without_access() {
}

@Test
@Ignore("""
Requires VaadinAwareSecurityContextHolderStrategyConfiguration that
in a custom Spring Security configuration without Vaadin helpers might not be imported.
Leaving the test here just as a template in case of future improvements.
""")
public void navigate_in_thread_with_access() {
open(LOGIN_PATH);
loginAdmin();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package com.vaadin.flow.spring.flowsecurity;

import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.openqa.selenium.WebDriver;

Expand All @@ -28,11 +27,6 @@
public class UIAccessContextIT extends AbstractIT {

@Test
@Ignore("""
Requires VaadinAwareSecurityContextHolderStrategyConfiguration that
in a custom Spring Security configuration without Vaadin helpers might not be imported.
Leaving the test here just as a template in case of future improvements.
""")
public void securityContextSetForUIAccess() throws Exception {
String expectedUserBalance = "Hello John the User, your bank account balance is $10000.00.";
String expectedAdminBalance = "Hello Emma the Admin, your bank account balance is $200000.00.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,16 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

import com.vaadin.flow.spring.security.VaadinAwareSecurityContextHolderStrategyConfiguration;

import static com.vaadin.flow.spring.security.VaadinSecurityConfigurer.vaadin;

@EnableWebSecurity
@Configuration
@Profile("default")
@Import(VaadinAwareSecurityContextHolderStrategyConfiguration.class)
public class SecurityConfig {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,13 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
Expand All @@ -50,15 +49,13 @@
import com.vaadin.flow.spring.flowsecurity.service.UserInfoService;
import com.vaadin.flow.spring.flowsecurity.views.LoginView;
import com.vaadin.flow.spring.security.UidlRedirectStrategy;
import com.vaadin.flow.spring.security.VaadinAwareSecurityContextHolderStrategyConfiguration;

import static com.vaadin.flow.spring.flowsecurity.service.UserInfoService.ROLE_ADMIN;
import static com.vaadin.flow.spring.security.VaadinSecurityConfigurer.vaadin;

@EnableWebSecurity
@Configuration
@Profile("default")
@Import(VaadinAwareSecurityContextHolderStrategyConfiguration.class)
public class SecurityConfig {

private final UserInfoService userInfoService;
Expand Down Expand Up @@ -171,9 +168,10 @@ public UserDetails loadUserByUsername(String username)
}

@Bean
@DependsOn("VaadinSecurityContextHolderStrategy")
public SwitchUserFilter switchUserFilter() {
public SwitchUserFilter switchUserFilter(
SecurityContextHolderStrategy securityContextHolderStrategy) {
SwitchUserFilter filter = new SwitchUserFilter();
filter.setSecurityContextHolderStrategy(securityContextHolderStrategy);
filter.setUserDetailsService(userDetailsService());
filter.setSwitchUserMatcher(PathPatternRequestMatcher
.pathPattern(HttpMethod.GET, "/impersonate"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
*/
package com.vaadin.flow.spring.flowsecurity;

import java.util.Collection;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

Expand All @@ -42,6 +45,14 @@ public UserInfo getAuthenticatedUserInfo() {
return userInfoService.findByUsername(userDetails.get().getUsername());
}

public SecurityContext getSecurityContext() {
return authenticationContext.getSecurityContext();
}

public Collection<? extends GrantedAuthority> getAuthorities() {
return authenticationContext.getGrantedAuthorities();
}

public void logout() {
authenticationContext.logout();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.concurrent.TimeUnit;

import org.springframework.security.concurrent.DelegatingSecurityContextRunnable;
import org.springframework.security.core.context.SecurityContextHolder;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
Expand Down Expand Up @@ -63,7 +62,7 @@ public AdminView(SecurityUtils securityUtils) {
}
};
Runnable wrappedRunnable = new DelegatingSecurityContextRunnable(
doNavigation, SecurityContextHolder.getContext());
doNavigation, securityUtils.getSecurityContext());
new Thread(wrappedRunnable).start();
});
add(accessRolePrefixedAdminPageFromThread);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.concurrent.TimeUnit;

import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.switchuser.SwitchUserFilter;

import com.vaadin.flow.component.Component;
Expand Down Expand Up @@ -125,10 +124,9 @@ private Component createDrawerContent(Tabs menu) {
.setLocation("impersonate?username=john")));
impersonate.setId("impersonate");
layout.add(impersonate);
} else if (SecurityContextHolder.getContext().getAuthentication()
.getAuthorities().stream().anyMatch(
auth -> SwitchUserFilter.ROLE_PREVIOUS_ADMINISTRATOR
.equals(auth.getAuthority()))) {
} else if (securityUtils.getAuthorities().stream().anyMatch(
auth -> SwitchUserFilter.ROLE_PREVIOUS_ADMINISTRATOR
.equals(auth.getAuthority()))) {
Button impersonate = new Button("Exit impersonation",
e -> getUI().ifPresent(ui -> ui.getPage()
.setLocation("impersonate/exit")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package com.vaadin.flow.spring.flowsecurity.views;

import org.springframework.security.concurrent.DelegatingSecurityContextRunnable;
import org.springframework.security.core.context.SecurityContextHolder;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
Expand All @@ -28,6 +27,7 @@
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.auth.AnonymousAllowed;
import com.vaadin.flow.spring.flowsecurity.SecurityUtils;

@Route(value = "", layout = MainView.class)
@PageTitle("Public View")
Expand All @@ -37,7 +37,7 @@ public class PublicView extends FlexLayout {

public static final String BACKGROUND_NAVIGATION_ID = "backgroundNavi";

public PublicView() {
public PublicView(SecurityUtils securityUtils) {
setFlexDirection(FlexDirection.COLUMN);
setHeightFull();

Expand Down Expand Up @@ -65,7 +65,7 @@ public PublicView() {
};
Runnable wrappedRunnable = new DelegatingSecurityContextRunnable(
navigateToAdmin,
SecurityContextHolder.getContext());
securityUtils.getSecurityContext());
new Thread(wrappedRunnable).start();
});
backgroundNavigation.setId(BACKGROUND_NAVIGATION_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,16 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

import com.vaadin.flow.spring.security.VaadinAwareSecurityContextHolderStrategyConfiguration;

import static com.vaadin.flow.spring.security.VaadinSecurityConfigurer.vaadin;

@EnableWebSecurity
@Configuration
@Profile("default")
@Import(VaadinAwareSecurityContextHolderStrategyConfiguration.class)
public class SecurityConfig {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,16 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

import com.vaadin.flow.spring.security.VaadinAwareSecurityContextHolderStrategyConfiguration;

import static com.vaadin.flow.spring.security.VaadinSecurityConfigurer.vaadin;

@EnableWebSecurity
@Configuration
@Profile("default")
@Import(VaadinAwareSecurityContextHolderStrategyConfiguration.class)
public class SecurityConfig {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,41 @@
*/
package com.vaadin.flow.spring;

import java.util.Objects;
import java.util.function.Function;
import java.util.function.Supplier;

import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

/**
* Helpers for authentication related tasks.
*/
public class AuthenticationUtil {

private static Supplier<SecurityContext> securityContextSupplier = SecurityContextHolder::getContext;

/**
* Sets the supplier for providing a custom SecurityContext.
*
* @param supplier
* the supplier function used to provide a SecurityContext
*/
public static void setSecurityContextSupplier(
Supplier<SecurityContext> supplier) {
securityContextSupplier = Objects.requireNonNull(supplier,
"SecurityContext supplier cannot be null");
}

/**
* Gets the authenticated user from the Spring SecurityContextHolder.
*
* @return the authenticated user or {@code null}
*/
public static Authentication getSecurityHolderAuthentication() {
Authentication authentication = SecurityContextHolder.getContext()
Authentication authentication = securityContextSupplier.get()
.getAuthentication();
if (authentication instanceof AnonymousAuthenticationToken) {
return null;
Expand Down
Loading
Loading