Hi everyone, I have many different api endpoints, I also have a swagger that I want to access via BasicAuth, how can I prevent Vaadin redirecting from all pages from BasicAuth to /backoffice/login. Thanks in advance!
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends VaadinWebSecurity {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final DatabaseUserDetailsService databaseUserDetailsService;
private final PasswordEncoder bcryptPasswordEncoder;
private final CustomVaadinAuthenticationProvider customVaadinAuthenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
// Authentication provider
configureAuthenticationProvider(http.getSharedObject(AuthenticationManagerBuilder.class));
setLoginView(http, "/login", "/login");
super.configure(http);
}
/**
* Swagger filter via Basicauth
*/
@Bean
@Order(1)
public SecurityFilterChain swaggerSecurityFilterChain(HttpSecurity http) throws Exception {
http
.securityMatcher("/swagger-ui/**", "/v3/api-docs/**")
.csrf(CsrfConfigurer::disable)
.csrf(csrf -> csrf.ignoringRequestMatchers(AntPathRequestMatcher.antMatcher("/swagger-ui/**"),
AntPathRequestMatcher.antMatcher("/v3/api-docs/**")))
.authorizeHttpRequests(auth -> auth
// Require authentication for all Swagger requests
.anyRequest().hasAnyAuthority(RoleName.ROLE_ADMIN.name(), RoleName.ROLE_EDITOR.name()))
// Turn on the BasicAuth
.httpBasic(Customizer.withDefaults())
// Turn off the session
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
return http.build();
}
/**
* Filter for access to ento -users /**, available only to admin
*/
@Bean
@Order(2)
public SecurityFilterChain adminSecurityFilterChain(HttpSecurity http) throws Exception {
http
.cors(customizer->{})
.securityMatcher("/users/**")
.csrf(CsrfConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/users/activate/*", "/users/archive/*")
.hasAnyAuthority(RoleName.ROLE_ADMIN.name(), RoleName.ROLE_APPLICATION.name())
.requestMatchers("/users/email")
.hasAuthority(RoleName.ROLE_DEVELOPER.name())
// Only for admins
.anyRequest().hasAuthority(RoleName.ROLE_ADMIN.name()))
// Turn on the BasicAuth
.httpBasic(Customizer.withDefaults())
// JWT support
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
// Turn off the session
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
return http.build();
}
/**
* Vaadin admin configuration
*/
@Bean
@Order(3)
public SecurityFilterChain vaadinSecurityFilterChain(HttpSecurity http) throws Exception {
http
.securityMatcher("/", "/backoffice/**")
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/backoffice/login/**").permitAll())
.formLogin(form -> form
.loginPage("/backoffice/login").permitAll()
.loginProcessingUrl("/backoffice/login")
.defaultSuccessUrl("/backoffice/", true))
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));
return http.build();
}
protected void configureAuthenticationProvider(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(customVaadinAuthenticationProvider);
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(databaseUserDetailsService);
provider.setPasswordEncoder(bcryptPasswordEncoder);
return provider;
}
}
I don’t understand the reason behind your vaadinSecurityFilterChain bean. It looks like to me that in this way you are creating an additional filter chain that is not related to the one provided by VaadinWebSecurity.
If your goal is to customize the Vaadin filter chain, I think you should instead override the VaadinWebSecurity.filterChain method and add the same @Bean(name = "VaadinSecurityFilterChainBean") annotation on the overriding method.
Thanks, I would like to disallow automatic redirects other than from /backoffice/ to /backoffice/login. Do you know of any examples of how I could do this?
Sorry, I don’t understand what redirects are you talking about.
Do you mean you are redirected to /backoffice/login when accessing, for example /users/something, instead of having basic authentication triggered?
Yes. I have many filterChains with different authentication and I don’t want to merge them into one configuration. And I want to remove the redirect from all closed pages to /backoffice/login
Could you please explain what do you mean by “closed pages”?
I am assuming the URIs protected by non-Vaadin security filter chain, are not Vaadin views.
Did you already try the previous suggestion of overriding VaadinWebSecurity.filterChain method?
By “closed pages,” I meant pages that are restricted to unauthenticated users. I wrote a small filterChain with @Bean(name = "VaadinSecurityFilterChainBean"), but it doesn’t work as expected. If a user is on a page that does not start with /backoffice/, there should be no automatic redirect to /backoffice/login. However, the user is still being redirected there.
Could you please suggest how I can modify the filterChain to prevent the automatic redirect to /backoffice/login for unauthenticated users? I tried adding http.authorizeHttpRequests(auth -> auth.requestMatchers("/**").permitAll()), but it doesn’t work properly.
Can you provide additional information about your application?
Is Vaadin Servlet mapped to root (/*, that is the default) or do you have a custom mapping /backoffice/*?
Are resources under /users/** Vaadin views or different technology?
setLoginView(http, “/login”, “/login”);
Login view setting seems incorrect; shouldn’t it be /backoffice/login? Does this path match with the path of @Route annotation on the View? Or is the login page not a Vaadin view?
I tested your configuration locally, only changing the setLoginView part, and if I do a request to /users/something I can see the basic auth login dialog pop up, no redirects to the login view. In my example, /users/something is served by a @RestController
I have a large multi-module application with a huge number of API endpoints spread across different filterChain configurations. I was asked to integrate an admin panel with URLs starting with /backoffice/. I configured the settings in the application file:
I’m sorry, but I cannot reproduce the problem.
In your configuration, I can see only a couple of things that can be modified:
do not add another filter chain called vaadinSecurityFilterChain. As reported previously, override the filterChain method of VaadinWebSecurity if you want to apply the @Order annotation(and add the same@Bean annotation as the overridden method)
setLoginView can use the login view class
securityMatcher("/", "/backoffice/**"): since you have a custom mapping for VaadinServlet make sure to use an AntPathRequestMatcher instead of an MVC request matcher (http.securityMatcher(new AntPathRequestMatcher("/backoffice/**")). My opinion is that / should not be added.
I don’t know how the JwtAuthenticationFilter filter works. Make sure it is the one that’s doing the redirecting.
I suggest you to set TRACE log level for Spring Security and analyze the logs to understand what’s going on (logging.level.org.springframework.security.web = trace)