1
0

use Spring-Props for CORS-config, move CORS-config to BaseWebSecurityConfig and add tests (#212)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/212
Reviewed-by: Marc Sandlus <hsh-marcsandlus@noreply.dev.hostsharing.net>
This commit is contained in:
Michael Hoennig
2026-03-21 13:55:43 +01:00
parent 3a24e1c726
commit 28eebbc95a
9 changed files with 273 additions and 35 deletions
@@ -3,9 +3,6 @@ package net.hostsharing.hsadminng;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
@OpenAPIDefinition
@@ -14,23 +11,4 @@ public class HsadminNgApplication {
public static void main(String[] args) {
SpringApplication.run(HsadminNgApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
// TODO: to enable testing, we should use Spring config
String allowedOrigins = System.getenv("ALLOWED_ORIGINS");
if (allowedOrigins == null || allowedOrigins.length() <= 1) {
allowedOrigins = "/**";
}
registry.addMapping("/api/**")
.allowedOrigins(allowedOrigins)
.allowedMethods("GET", "PUT", "POST", "PATCH", "DELETE");
}
};
}
}
@@ -3,10 +3,12 @@ package net.hostsharing.hsadminng.config;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import lombok.SneakyThrows;
import lombok.val;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.lang.NonNull;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -14,6 +16,8 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import jakarta.servlet.http.HttpServletResponse;
@@ -48,7 +52,7 @@ public abstract class BaseWebSecurityConfig {
.oauth2ResourceServer(oauth ->
oauth.jwt(Customizer.withDefaults()))
.csrf(AbstractHttpConfigurer::disable)
.cors(AbstractHttpConfigurer::disable)
.cors(Customizer.withDefaults())
.exceptionHandling(exception -> exception
.authenticationEntryPoint((request, response, authException) ->
// For unknown reason Spring security returns 403 FORBIDDEN for a BadCredentialsException.
@@ -75,4 +79,24 @@ public abstract class BaseWebSecurityConfig {
// For fake-jwt profile, use the same RSA key as JwtFakeBearer
return NimbusJwtDecoder.withPublicKey(RSA_KEY.toRSAPublicKey()).build();
}
@Bean
public WebMvcConfigurer corsConfigurer(
@Value("${hsadminng.cors.allowed-origins:*}") final String corsAllowedOrigins) {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(@NonNull final CorsRegistry registry) {
val allowedOrigins = (corsAllowedOrigins != null && !corsAllowedOrigins.isEmpty())
? corsAllowedOrigins.split(",")
: new String[]{"*"};
registry.addMapping("/api/ping")
.allowedOrigins("*")
.allowedMethods("GET");
registry.addMapping("/api/**").allowedOrigins(allowedOrigins)
.allowedMethods("GET", "PUT", "POST", "PATCH", "DELETE");
}
};
}
}
@@ -17,6 +17,7 @@ public class PingController implements TestApi {
private MessageTranslator messageTranslator;
@Timed("app.api.ping")
@Override
public ResponseEntity<String> ping() {
// HOWTO translate text with placeholders - also see in resource files i18n/messages_*.properties.
final var translatedMessage = messageTranslator.translate("test.pinged--in-your-language");
@@ -24,7 +25,18 @@ public class PingController implements TestApi {
}
@Timed("app.api.pong")
@Override
public ResponseEntity<String> pong() {
return createPongResponse();
}
@Timed("app.api.pong")
@Override
public ResponseEntity<String> pongPost() {
return createPongResponse();
}
private ResponseEntity<String> createPongResponse() {
final var userName = SecurityContextHolder.getContext().getAuthentication().getName();
// HOWTO translate text with placeholders - also see in resource files i18n/messages_*.properties.
final var translatedMessage = messageTranslator.translate("test.ponged-{0}--in-your-language", userName);
@@ -33,3 +33,14 @@ paths:
'text/plain':
schema:
type: string
post:
tags:
- test
operationId: pongPost
responses:
"200":
description: OK
content:
'text/plain':
schema:
type: string
+2
View File
@@ -70,6 +70,8 @@ spring:
hsadminng:
postgres:
leakproof:
cors:
allowed-origin: ${ALLOWED_ORIGINS} // for compatibility with env-based CORS-configuration
metrics:
distribution: