This topic is the discussion thread for the Vaadin documentation page How to enable security in your Vaadin application.
Questions, feedback, and comments are welcome here.
This topic is the discussion thread for the Vaadin documentation page How to enable security in your Vaadin application.
Questions, feedback, and comments are welcome here.
This is a great way to define which pages should be accessible after login:
@RolesAllowed("ADMIN")
But I'm missing an example or description here how the opposite can be achieved. For instance to hide the "register" page, after someone has logged in.
You could use a `forwardTo` in a `beforeEnter` method: https://vaadin.com/docs/latest/routing/lifecycle/#forwarding. Check the Security Utilities chapter https://vaadin.com/docs/latest/security/enabling-security/#security-utilities how to see if a user is logged in.
It is a common use-case for a Vaadin/Spring application to have a REST API as well the web UI which have different authentication needs. For the UI users have to log-in, for the rest API you need a token in the header. It would be helpful to have a chapter in the advanced security section of documentation to show an example configuration class for this.
I agree that this would be great to have. I have spent hours on this not realizing this and thinking something was wrong with AntMatchers or something in that area.
Do you have a tutorial for this? I could definitely use it!
I had a working Spring Security Config that handled both a REST API and Vaadin. Now after updating to Spring Boot 3 and Vaadin 24 it is broken. Failed authentication results in a redirect to the Vaadin log-in screen instead of returning 401 Unauthorized. Can anyone see what's wrong/missing in the config?
@Configuration
@Order(1)
public static class MyRestApiSecurity {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.securityMatcher("/api/**")
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeHttpRequests(auth -> auth
.anyRequest()
.hasAuthority(AppRoles.API))
.httpBasic()
.authenticationEntryPoint(new RestAuthenticationEntryPoint());
}
}
@Configuration
@Order(2)
public static class MyVaadinSecurity extends VaadinWebSecurity {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
setLoginView(http, LoginView.class);
}
}
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, “Unauthorized”);
}
}
@Component
public class AuthenticatedUser {
private final UserRepository userRepository;
@Autowired
public AuthenticatedUser(UserRepository userRepository) {
this.userRepository = userRepository;
}
private Optional<Authentication> getAuthentication() {
SecurityContext context = SecurityContextHolder.getContext();
return Optional.ofNullable(context.getAuthentication())
.filter(authentication -> !(authentication instanceof AnonymousAuthenticationToken));
}
public Optional<User> get() {
return getAuthentication().map(authentication -> userRepository.findByUsername(authentication.getName()));
}
public void logout() {
UI.getCurrent().getPage().setLocation(SecurityConfiguration.LOGOUT_URL);
SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
logoutHandler.logout(VaadinServletRequest.getCurrent().getHttpServletRequest(), null, null);
}
}
Why do i get "cannot access HttpServletRequest"?
Perhaps servlet-api jar is not on your classpath.
Hi...
After updating to Spring 3.1.2, My application fails with an Exception :
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'VaadinSecurityFilterChainBean' defined in class path resource [dk/eg/aspect4/stackmonitor/SecurityConfiguration.class]: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'filterChain' threw exception with message: This method cannot decide whether these patterns are Spring MVC patterns or not. If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); otherwise, please use requestMatchers(AntPathRequestMatcher).
This Exception is thrown when I call
setLoginView(http, LoginView.class);
Everything worked fine with Spring Boot 3.1.1
And my code is just like in the example above
This has been fixed in the latest Flow versions, for example, Flow 24.1.5 (see release notes). That Flow version and the fix is available in the Vaadin 24.1.4 release, and later releases.
I get warnings following this documentation due to deprecated API being used. This documentation need some updates.
@Deprecated(since = "6.1", forRemoval = true)
public AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry authorizeHttpRequests()
throws Exception {
Is it possible to require login just for a dialog component?
Your question is not very clear, but you can get the authentication details in code, as seen in the chapter “Security Utilities” (How to enable security in your Vaadin application) and create an arbitrary user flow based on that.
Thanks for your reply. Let me try to concretize my scenario. First of all, enabling security in genaral works very well. I use
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
and added @PermitAll to one of my views and user is forced to login.
What Im asking for is the following scenario:
Id like to have a view without login (security) so I added @AnonymousAllowed to it. Works well, no login required. In this view, I open a dialog (dialog.open()). And Id like this dialog to be secured, so that if the user want to see the content of the dialog it has to log in. Tried to add @PermitAll to the dialog but doesnt change anthing. I assume, that the dialog is opened in the context of the view where I added @AnonymousAllowed as its not a separate view, just a dialog. Is their any way of forcing the dialog to require login?
As I mentioned above, you can access the authentication details in code, so you can check those before opening the Dialog. Opening a Dialog is not a navigational action, so it’s not affected by the view-based security annotations only.
Read the details but cant figure out how to force a login with AuthenticationContext. Just found methods "to access authenticated user details and to simplify logout handling".
In my case, roles and associated views are dynamically configurated by user as needed. How to implement the feature via annotations and SecurityConfiguration.
I had the same question and eventually got it to work. The two key items were:
The second one is tricky because you have to do it AFTER Vaadin does its config.
Here's the end result:
@EnableWebSecurity
@Configuration
public class SecurityConfig extends VaadinWebSecurity {
// VaadinWebSecurity
@Override
protected void configure(HttpSecurity http) throws Exception {
// These URLs should be freely accessible
final List<String> freePaths = List.of(
“/error”,
“/images/**/*”,
“/api/resthook1”,
“/api/resthook2”
);
// Allow access without authenticating
http.authorizeHttpRequests(auth ->
freePaths.forEach(path ->
Stream.of(HttpMethod.GET, HttpMethod.POST).forEach(method ->
auth.requestMatchers(AntPathRequestMatcher.antMatcher(method, path)).permitAll())));
// Apply Vaadin config
super.configure(http);
// Disable CSRF checks (POST requests)
http.csrf(csrf ->
freePaths.forEach(path ->
csrf.ignoringRequestMatchers(AntPathRequestMatcher.antMatcher(HttpMethod.POST, path))));
// Configure where to login
this.setLoginView(http, LoginView.class);
}
// etc...
Another thing that's not addressed anywhere is how to programmatically set the logged-in user, for example, at the end of a successful sign-up workflow.
Here's the secret Vaadin magic that seems to work:
import org.springframework.security.web.context.HttpSessionSecurityContextRepository; ... VaadinSession.getCurrent().getSession().setAttribute( HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context)
See VaadinAwareSecurityContextHolderStrategy.java for details.