feat: add CAMELEER_CORS_ALLOWED_ORIGINS for multi-origin CORS support
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m7s
CI / docker (push) Successful in 41s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 37s

Behind a reverse proxy the browser sends Origin matching the proxy's
public URL, which the single-origin CAMELEER_UI_ORIGIN rejects.
New env var accepts comma-separated origins and takes priority over
UI_ORIGIN, which remains as a backwards-compatible fallback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-06 00:41:00 +02:00
parent 0609220cdf
commit 083cb8b9ec
6 changed files with 16 additions and 6 deletions

View File

@@ -41,6 +41,7 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@@ -217,11 +218,14 @@ public class SecurityConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource(SecurityProperties properties) {
CorsConfiguration config = new CorsConfiguration();
String origin = properties.getUiOrigin();
if (origin != null && !origin.isBlank()) {
config.setAllowedOrigins(List.of(origin));
String corsOrigins = properties.getCorsAllowedOrigins();
if (corsOrigins != null && !corsOrigins.isBlank()) {
config.setAllowedOrigins(Arrays.stream(corsOrigins.split(","))
.map(String::trim).filter(s -> !s.isEmpty()).toList());
} else {
config.setAllowedOrigins(List.of("http://localhost:5173"));
String origin = properties.getUiOrigin();
config.setAllowedOrigins(List.of(
origin != null && !origin.isBlank() ? origin : "http://localhost:5173"));
}
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(List.of("*"));

View File

@@ -21,6 +21,7 @@ public class SecurityProperties {
private String oidcJwkSetUri;
private String oidcAudience;
private boolean oidcTlsSkipVerify;
private String corsAllowedOrigins;
public long getAccessTokenExpiryMs() { return accessTokenExpiryMs; }
public void setAccessTokenExpiryMs(long accessTokenExpiryMs) { this.accessTokenExpiryMs = accessTokenExpiryMs; }
@@ -46,4 +47,6 @@ public class SecurityProperties {
public void setOidcAudience(String oidcAudience) { this.oidcAudience = oidcAudience; }
public boolean isOidcTlsSkipVerify() { return oidcTlsSkipVerify; }
public void setOidcTlsSkipVerify(boolean oidcTlsSkipVerify) { this.oidcTlsSkipVerify = oidcTlsSkipVerify; }
public String getCorsAllowedOrigins() { return corsAllowedOrigins; }
public void setCorsAllowedOrigins(String corsAllowedOrigins) { this.corsAllowedOrigins = corsAllowedOrigins; }
}

View File

@@ -54,6 +54,7 @@ security:
oidc-jwk-set-uri: ${CAMELEER_OIDC_JWK_SET_URI:}
oidc-audience: ${CAMELEER_OIDC_AUDIENCE:}
oidc-tls-skip-verify: ${CAMELEER_OIDC_TLS_SKIP_VERIFY:false}
cors-allowed-origins: ${CAMELEER_CORS_ALLOWED_ORIGINS:}
springdoc: