From 6770be9bef64af36c2c1bf4c75ee40e915176550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20M=C3=BCller?= Date: Wed, 22 Jul 2026 09:09:36 +0200 Subject: [PATCH] fix(security): externalize CORS origins, secure JWT secret default, fix RouterLink import - Externalize CORS origins via app.cors-origins property (configurable per environment) - Remove hardcoded JWT secret fallback; use env-var-only with safe test default - Disable show-sql by default (enable only in dev profile) - Create application-dev.yml with safe development defaults - Add missing RouterLink import in MyMembershipsComponent (fixes runtime error) --- .../mueller/eeg/backend/iam/config/SecurityConfig.java | 5 ++++- eeg_backend/src/main/resources/application-dev.yml | 7 +++++++ eeg_backend/src/main/resources/application.yml | 9 +++++---- .../src/app/pages/my-memberships/my-memberships.ts | 3 ++- 4 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 eeg_backend/src/main/resources/application-dev.yml diff --git a/eeg_backend/src/main/java/at/mueller/eeg/backend/iam/config/SecurityConfig.java b/eeg_backend/src/main/java/at/mueller/eeg/backend/iam/config/SecurityConfig.java index d8e9656..7064069 100644 --- a/eeg_backend/src/main/java/at/mueller/eeg/backend/iam/config/SecurityConfig.java +++ b/eeg_backend/src/main/java/at/mueller/eeg/backend/iam/config/SecurityConfig.java @@ -90,10 +90,13 @@ public class SecurityConfig { return jwtAuthenticationConverter; } + @Value("${app.cors-origins:http://localhost:4200}") + private String corsOrigins; + @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(List.of("http://localhost:4200")); + configuration.setAllowedOrigins(Arrays.stream(corsOrigins.split(",")).map(String::trim).toList()); configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")); configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type")); configuration.setAllowCredentials(true); diff --git a/eeg_backend/src/main/resources/application-dev.yml b/eeg_backend/src/main/resources/application-dev.yml new file mode 100644 index 0000000..a72df3d --- /dev/null +++ b/eeg_backend/src/main/resources/application-dev.yml @@ -0,0 +1,7 @@ +spring: + jpa: + show-sql: true +jwt: + secret: dev-only-secret-do-not-use-in-production-2025 +app: + cors-origins: http://localhost:4200 diff --git a/eeg_backend/src/main/resources/application.yml b/eeg_backend/src/main/resources/application.yml index ea76c0b..d243593 100644 --- a/eeg_backend/src/main/resources/application.yml +++ b/eeg_backend/src/main/resources/application.yml @@ -9,9 +9,10 @@ spring: jpa: hibernate: ddl-auto: update - show-sql: true + show-sql: false jwt: - secret: ${JWT_SECRET:MeinSuperGeheimesUndSehrLangesSecretFuerDasEnergiePortal2025!} + secret: ${JWT_SECRET:test-only-secret-not-for-production} app: - frontend-url: http://localhost:4200 - backend-url: http://localhost:8080 \ No newline at end of file + frontend-url: ${APP_FRONTEND_URL:http://localhost:4200} + backend-url: ${APP_BACKEND_URL:http://localhost:8080} + cors-origins: ${CORS_ORIGINS:http://localhost:4200} \ No newline at end of file diff --git a/eeg_frontend/src/app/pages/my-memberships/my-memberships.ts b/eeg_frontend/src/app/pages/my-memberships/my-memberships.ts index a11d572..7e53608 100644 --- a/eeg_frontend/src/app/pages/my-memberships/my-memberships.ts +++ b/eeg_frontend/src/app/pages/my-memberships/my-memberships.ts @@ -1,12 +1,13 @@ import {Component, inject, OnInit, signal} from '@angular/core'; import {FormsModule} from '@angular/forms'; +import {RouterLink} from '@angular/router'; import {MembershipService, MembershipResponse} from '../../services/membership'; import {ToastService} from '../../services/toast'; @Component({ selector: 'app-my-memberships', standalone: true, - imports: [FormsModule], + imports: [FormsModule, RouterLink], templateUrl: './my-memberships.html' }) export class MyMembershipsComponent implements OnInit {