Enhanced CORS configuration for OAuth2 and role-based tab visibility in frontend:
- **Backend**: Added separate CORS settings for `/oauth2/token` endpoint with enhanced origin handling based on new `lcc.allowed_oauth_token_cors` property. - **Frontend**: Updated `Config.vue` to conditionally display `nodesTab` and `bulkOperationsTab` based on user roles.
This commit is contained in:
parent
e1791942cb
commit
a289cce805
3 changed files with 77 additions and 48 deletions
|
|
@ -90,12 +90,16 @@ export default {
|
|||
tabs.push(this.materialsTab);
|
||||
}
|
||||
|
||||
if (this.activeUserStore.isSuper || this.activeUserStore.isMaterial || this.activeUserStore.isPackaging || this.activeUserStore.isFreight) {
|
||||
tabs.push(this.nodesTab);
|
||||
}
|
||||
|
||||
if (this.activeUserStore.allowRates)
|
||||
tabs.push(this.ratesTab);
|
||||
|
||||
if (this.activeUserStore.isSuper || this.activeUserStore.isMaterial || this.activeUserStore.isPackaging || this.activeUserStore.isFreight) {
|
||||
tabs.push(this.bulkOperationsTab);
|
||||
}
|
||||
|
||||
|
||||
return tabs;
|
||||
|
|
|
|||
|
|
@ -57,9 +57,12 @@ public class SecurityConfig {
|
|||
@Value("${lcc.allowed_cors}")
|
||||
private String allowedCors;
|
||||
|
||||
@Value("${lcc.allowed_oauth_token_cors:*}") // Default: alle Origins
|
||||
private String oauthTokenCors;
|
||||
|
||||
@Bean
|
||||
@Profile("!dev & !test") // Only active when NOT in dev profile
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtTokenService jwtTokenService) throws Exception {
|
||||
public SecurityFilterChain prodSecurityFilterChain(HttpSecurity http, JwtTokenService jwtTokenService) throws Exception {
|
||||
http
|
||||
.cors(cors -> cors.configurationSource(prodCorsConfigurationSource())) // Production CORS
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
|
|
@ -98,30 +101,31 @@ public class SecurityConfig {
|
|||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Profile("dev | test")
|
||||
public CorsConfigurationSource devCorsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOriginPatterns(List.of("http://localhost:*"));
|
||||
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
configuration.setAllowedHeaders(List.of("*"));
|
||||
configuration.setAllowCredentials(true);
|
||||
configuration.setMaxAge(3600L);
|
||||
|
||||
configuration.setExposedHeaders(Arrays.asList("X-Total-Count", "X-Page-Count", "X-Current-Page"));
|
||||
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
|
||||
// Production CORS Configuration
|
||||
@Bean
|
||||
@Profile("!dev & !test")
|
||||
public CorsConfigurationSource prodCorsConfigurationSource() {
|
||||
|
||||
|
||||
// CORS for /oauth2/token
|
||||
CorsConfiguration tokenConfiguration = new CorsConfiguration();
|
||||
if ("*".equals(oauthTokenCors)) {
|
||||
tokenConfiguration.setAllowedOriginPatterns(List.of("*"));
|
||||
} else {
|
||||
String[] tokenOrigins = oauthTokenCors.split(",");
|
||||
for (int i = 0; i < tokenOrigins.length; i++) {
|
||||
tokenOrigins[i] = tokenOrigins[i].trim();
|
||||
}
|
||||
if (tokenOrigins.length != 0) {
|
||||
tokenConfiguration.setAllowedOrigins(Arrays.asList(tokenOrigins));
|
||||
}
|
||||
}
|
||||
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
|
||||
if ("*".equals(allowedCors)) {
|
||||
configuration.setAllowedOriginPatterns(List.of("*"));
|
||||
} else {
|
||||
// Parse comma-separated origins from property
|
||||
String[] origins = allowedCors.split(",");
|
||||
for (int i = 0; i < origins.length; i++) {
|
||||
|
|
@ -131,6 +135,8 @@ public class SecurityConfig {
|
|||
if (origins.length != 0) {
|
||||
configuration.setAllowedOrigins(Arrays.asList(origins));
|
||||
}
|
||||
}
|
||||
|
||||
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
configuration.setAllowedHeaders(List.of("*"));
|
||||
configuration.setAllowCredentials(true);
|
||||
|
|
@ -138,30 +144,12 @@ public class SecurityConfig {
|
|||
|
||||
configuration.setExposedHeaders(Arrays.asList("X-Total-Count", "X-Page-Count", "X-Current-Page"));
|
||||
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
source.registerCorsConfiguration("/oauth2/token", tokenConfiguration);
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public JwtAuthenticationConverter jwtAuthenticationConverter() {
|
||||
// Für Entra ID Tokens
|
||||
JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
|
||||
converter.setAuthoritiesClaimName("scp");
|
||||
converter.setAuthorityPrefix("SCOPE_");
|
||||
|
||||
JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
|
||||
jwtConverter.setJwtGrantedAuthoritiesConverter(converter);
|
||||
return jwtConverter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Profile("dev | test")
|
||||
public SecurityFilterChain devSecurityFilterChain(HttpSecurity http, UserRepository userRepository, JwtTokenService jwtTokenService) throws Exception {
|
||||
|
|
@ -188,6 +176,42 @@ public class SecurityConfig {
|
|||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Profile("dev | test")
|
||||
public CorsConfigurationSource devCorsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOriginPatterns(List.of("http://localhost:*"));
|
||||
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
configuration.setAllowedHeaders(List.of("*"));
|
||||
configuration.setAllowCredentials(true);
|
||||
configuration.setMaxAge(3600L);
|
||||
|
||||
configuration.setExposedHeaders(Arrays.asList("X-Total-Count", "X-Page-Count", "X-Current-Page"));
|
||||
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JwtAuthenticationConverter jwtAuthenticationConverter() {
|
||||
// Für Entra ID Tokens
|
||||
JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
|
||||
converter.setAuthoritiesClaimName("scp");
|
||||
converter.setAuthorityPrefix("SCOPE_");
|
||||
|
||||
JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
|
||||
jwtConverter.setJwtGrantedAuthoritiesConverter(converter);
|
||||
return jwtConverter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
@Profile("!dev & !test")
|
||||
public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService(UserRepository userRepository, GroupRepository groupRepository) {
|
||||
|
|
|
|||
|
|
@ -23,3 +23,4 @@ spring.flyway.baseline-on-migrate=true
|
|||
spring.sql.init.mode=never
|
||||
|
||||
lcc.allowed_cors=
|
||||
lcc.allowed_oauth_token_cors=*
|
||||
Loading…
Add table
Reference in a new issue