Files
bflows-bandi-be/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java
2024-12-13 20:57:58 +05:30

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")));
}
}