package org.gcube.isdashboard.config; import static org.springframework.security.config.Customizer.withDefaults; import org.gcube.isdashboard.security.*; import org.gcube.isdashboard.web.filter.SpaWebFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.FrameOptionsConfig; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.HttpStatusEntryPoint; import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher; import tech.jhipster.config.JHipsterProperties; import tech.jhipster.web.filter.CookieCsrfFilter; @Configuration @EnableMethodSecurity(securedEnabled = true) public class SecurityConfiguration { private final JHipsterProperties jHipsterProperties; public SecurityConfiguration(JHipsterProperties jHipsterProperties) { this.jHipsterProperties = jHipsterProperties; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors(withDefaults()) .csrf(csrf -> csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // See https://stackoverflow.com/q/74447118/65681 .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()) ) .addFilterAfter(new SpaWebFilter(), BasicAuthenticationFilter.class) .addFilterAfter(new CookieCsrfFilter(), BasicAuthenticationFilter.class) .headers(headers -> headers .contentSecurityPolicy(csp -> csp.policyDirectives(jHipsterProperties.getSecurity().getContentSecurityPolicy())) .frameOptions(FrameOptionsConfig::sameOrigin) .referrerPolicy(referrer -> referrer.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)) .permissionsPolicy(permissions -> permissions.policy( "camera=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), sync-xhr=()" ) ) ) .authorizeHttpRequests(authz -> // prettier-ignore authz .requestMatchers("/", "/index.html", "/*.js", "/*.map", "/*.css").permitAll() .requestMatchers("/*.ico", "/*.png", "/*.svg", "/*.webapp").permitAll() .requestMatchers("/app/**").permitAll() .requestMatchers("/i18n/**").permitAll() .requestMatchers("/content/**").permitAll() .requestMatchers("/swagger-ui/**").permitAll() .requestMatchers("/api/authenticate").permitAll() .requestMatchers("/api/admin/**").hasAuthority(AuthoritiesConstants.ADMIN) .requestMatchers("/api/**").authenticated() .requestMatchers("/v3/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN) .requestMatchers("/management/health").permitAll() .requestMatchers("/management/health/**").permitAll() .requestMatchers("/management/info").permitAll() .requestMatchers("/management/prometheus").permitAll() .requestMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN) ) .exceptionHandling(exceptionHanding -> exceptionHanding.defaultAuthenticationEntryPointFor( new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), new OrRequestMatcher(new AntPathRequestMatcher("/api/**")) ) ) .formLogin(formLogin -> formLogin .loginProcessingUrl("/api/authentication") .successHandler((request, response, authentication) -> response.setStatus(HttpStatus.OK.value())) .failureHandler((request, response, exception) -> response.setStatus(HttpStatus.UNAUTHORIZED.value())) .permitAll() ) .logout(logout -> logout.logoutUrl("/api/logout").logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()).permitAll() ); return http.build(); } }