142 lines
7.1 KiB
Java
142 lines
7.1 KiB
Java
package net.gepafin.tendermanagement.config;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.context.annotation.Bean;
|
|
import org.springframework.context.annotation.Configuration;
|
|
import org.springframework.http.HttpMethod;
|
|
import org.springframework.security.authentication.AuthenticationManager;
|
|
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
|
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.configuration.EnableWebSecurity;
|
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
import org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter;
|
|
import org.springframework.security.web.SecurityFilterChain;
|
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
|
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
import org.springframework.web.cors.CorsConfiguration;
|
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
|
import org.springframework.web.filter.CorsFilter;
|
|
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
|
|
import io.swagger.v3.oas.models.Components;
|
|
import io.swagger.v3.oas.models.OpenAPI;
|
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
|
import io.swagger.v3.oas.models.servers.Server;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
import net.gepafin.tendermanagement.config.jwt.JWTFilter;
|
|
import net.gepafin.tendermanagement.config.jwt.TokenProvider;
|
|
|
|
@Configuration
|
|
@EnableWebSecurity
|
|
@EnableMethodSecurity(prePostEnabled = true)
|
|
public class SecurityConfig {
|
|
private final TokenProvider tokenProvider;
|
|
private final SamlSuccessHandler samlSuccessHandler;
|
|
private final SamlFailureHandler samlFailureHandler;
|
|
|
|
@Value("${base-url}")
|
|
String baseUrl;
|
|
|
|
@Autowired
|
|
public SecurityConfig(TokenProvider tokenProvider, SamlSuccessHandler samlSuccessHandler, SamlFailureHandler samlFailureHandler) {
|
|
this.tokenProvider = tokenProvider;
|
|
this.samlSuccessHandler =samlSuccessHandler;
|
|
this.samlFailureHandler=samlFailureHandler;
|
|
}
|
|
|
|
|
|
@Bean
|
|
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
|
return config.getAuthenticationManager();
|
|
}
|
|
@Bean
|
|
public PasswordEncoder passwordEncoder() {
|
|
return new BCryptPasswordEncoder();
|
|
}
|
|
|
|
@Bean
|
|
public MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
|
|
return new MvcRequestMatcher.Builder(introspector);
|
|
}
|
|
|
|
@Bean
|
|
public WebSecurityCustomizer webSecurityCustomizer(MvcRequestMatcher.Builder mvc) {
|
|
return (web) -> web.ignoring().requestMatchers(mvc.pattern(HttpMethod.OPTIONS, "/**"))
|
|
.requestMatchers(new AntPathRequestMatcher("/i18n/**"))
|
|
.requestMatchers(new AntPathRequestMatcher("/content/**"))
|
|
.requestMatchers(new AntPathRequestMatcher("/swagger-ui/index.html"))
|
|
.requestMatchers(new AntPathRequestMatcher("/swagger-ui/**"));
|
|
}
|
|
|
|
|
|
@Bean
|
|
public CorsFilter corsFilter() {
|
|
|
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
|
|
|
CorsConfiguration config = new CorsConfiguration();
|
|
config.addAllowedOrigin("*");
|
|
config.addAllowedMethod("*");
|
|
config.addAllowedHeader("*");
|
|
config.setMaxAge(3600l);
|
|
|
|
if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) {
|
|
source.registerCorsConfiguration("/v1/**", config);
|
|
source.registerCorsConfiguration("/management/**", config);
|
|
source.registerCorsConfiguration("/v1/api-docs", config);
|
|
}
|
|
return new CorsFilter(source);
|
|
}
|
|
@Bean
|
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth
|
|
// Allow public access to the login endpoints
|
|
.requestMatchers("/v1/user/login").permitAll() // JWT-based login
|
|
.requestMatchers("/v1/user").permitAll() // User registration
|
|
.requestMatchers("/v1/user/sso/validate/existing-user/{token}").permitAll()
|
|
.requestMatchers("/v1/user/sso/validate/new-user/{token}").permitAll()
|
|
.requestMatchers("/v1/saml/**").permitAll() // JWT-based login
|
|
.requestMatchers("/saml2/**").permitAll() // SAML login initiation
|
|
.requestMatchers("/swagger-ui/**").permitAll() // Swagger docs
|
|
.requestMatchers("/v1/api-docs/**").permitAll() // API docs
|
|
.requestMatchers("/v1/user/reset-password/initiate").permitAll()
|
|
.requestMatchers("/v1/user/reset-password").permitAll()
|
|
.requestMatchers("/wss/**").permitAll() // if this is not running use this /gs-guide-websocket
|
|
.anyRequest().authenticated())
|
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
|
|
.exceptionHandling(exceptionHandling -> exceptionHandling
|
|
.authenticationEntryPoint((request, response, authException) -> {
|
|
// Send 403 Forbidden when there is no JWT token provided
|
|
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden: Authentication token is missing or invalid");
|
|
})
|
|
)
|
|
.addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class)
|
|
.addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class)
|
|
.addFilterBefore(new SamlRequestFilter(), Saml2WebSsoAuthenticationRequestFilter.class) // Add the custom SAML filter
|
|
.saml2Login(saml -> saml.defaultSuccessUrl("/")
|
|
.successHandler(samlSuccessHandler)
|
|
.failureHandler(samlFailureHandler));
|
|
|
|
return http.build();
|
|
}
|
|
|
|
@Bean
|
|
public OpenAPI customOpenAPI() {
|
|
return new OpenAPI()
|
|
.addServersItem(new Server().url("/"))
|
|
.addSecurityItem(new SecurityRequirement().addList("bearer-key"))
|
|
.components(new Components().addSecuritySchemes("bearer-key",
|
|
new SecurityScheme().type(SecurityScheme.Type.HTTP)
|
|
.scheme("bearer").bearerFormat("JWT")));
|
|
}
|
|
|
|
|
|
} |