From 762e9367ec1cdaa6e681ee983857b5c19a04fafa Mon Sep 17 00:00:00 2001 From: Chris Malloy Date: Mon, 27 Nov 2023 18:03:09 +0900 Subject: [PATCH] Enable CORS except for Public API --- .../jasper/config/SecurityConfiguration.java | 29 ++++++++++++------- .../java/jasper/security/jwt/JWTFilter.java | 5 ++++ .../jasper/web/rest/ReplicateController.java | 2 ++ src/main/resources/config/application-dev.yml | 14 ++++----- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main/java/jasper/config/SecurityConfiguration.java b/src/main/java/jasper/config/SecurityConfiguration.java index 46c83a43..4848a661 100644 --- a/src/main/java/jasper/config/SecurityConfiguration.java +++ b/src/main/java/jasper/config/SecurityConfiguration.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; @@ -15,6 +16,8 @@ import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; +import org.springframework.security.web.csrf.CsrfTokenRepository; import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; import org.springframework.web.context.annotation.ApplicationScope; import org.springframework.web.cors.CorsConfiguration; @@ -87,8 +90,6 @@ private boolean profile(String profile) { public void configure(HttpSecurity http) throws Exception { // @formatter:off http - .csrf() - .disable() .exceptionHandling() .authenticationEntryPoint(problemSupport) .accessDeniedHandler(problemSupport) @@ -107,25 +108,33 @@ public void configure(HttpSecurity http) throws Exception { .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .apply(securityConfigurerAdapter()) + .and() + .authorizeRequests() + .antMatchers(HttpMethod.OPTIONS, "/api/v1/**").permitAll() .and() .headers() .frameOptions() .sameOrigin() .and() - .cors().configurationSource(request -> { - var config = new CorsConfiguration(); - config.addAllowedMethod("*"); - config.applyPermitDefaultValues(); - return config; - }); - // @formatter:on + .csrf() + .csrfTokenRepository(csrfTokenRepository()) + .ignoringAntMatchers("/api/v1/repl/**") // Public API + ; // @formatter:on } - private JWTConfigurer securityConfigurerAdapter() { + @Bean + JWTConfigurer securityConfigurerAdapter() { logger.info("Minimum Role: {}", props.getMinRole()); return new JWTConfigurer(props, tokenProvider, defaultTokenProvider); } + @Bean + CsrfTokenRepository csrfTokenRepository() { + var r = CookieCsrfTokenRepository.withHttpOnlyFalse(); + r.setSecure(false); // Required when using SSL terminating gateway + return r; + } + @Bean @ApplicationScope public RoleHierarchy roleHierarchy() { diff --git a/src/main/java/jasper/security/jwt/JWTFilter.java b/src/main/java/jasper/security/jwt/JWTFilter.java index 66960fde..d1db0f21 100644 --- a/src/main/java/jasper/security/jwt/JWTFilter.java +++ b/src/main/java/jasper/security/jwt/JWTFilter.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.util.StringUtils; import org.springframework.web.filter.GenericFilterBean; @@ -38,6 +39,10 @@ public JWTFilter(Props props, TokenProvider tokenProvider, TokenProviderImplDefa @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { var httpServletRequest = (HttpServletRequest) servletRequest; + if ("OPTIONS".equalsIgnoreCase(httpServletRequest.getMethod())) { + SecurityContextHolder.getContext().setAuthentication(new PreAuthenticatedAuthenticationToken("options", null)); + } + var origin = resolveOrigin(httpServletRequest); var jwt = resolveToken(httpServletRequest); if (tokenProvider.validateToken(jwt, origin)) { diff --git a/src/main/java/jasper/web/rest/ReplicateController.java b/src/main/java/jasper/web/rest/ReplicateController.java index a72c4de6..c6835d07 100644 --- a/src/main/java/jasper/web/rest/ReplicateController.java +++ b/src/main/java/jasper/web/rest/ReplicateController.java @@ -32,6 +32,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort.Direction; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -47,6 +48,7 @@ import static jasper.domain.proj.HasOrigin.ORIGIN_LEN; import static jasper.repository.filter.Query.QUERY_LEN; +@CrossOrigin @RestController @RequestMapping("api/v1/repl") @Validated diff --git a/src/main/resources/config/application-dev.yml b/src/main/resources/config/application-dev.yml index d6a382a5..b5c25a08 100644 --- a/src/main/resources/config/application-dev.yml +++ b/src/main/resources/config/application-dev.yml @@ -80,13 +80,13 @@ jasper: scrape-interval-min: 5 # CORS is disabled by default on microservices, as you should access them through a gateway. # If you want to enable it, please uncomment the configuration below. - # cors: - # allowed-origins: "http://localhost:9000,https://localhost:9000" - # allowed-methods: "*" - # allowed-headers: "*" - # exposed-headers: "Authorization,Link,X-Total-Count" - # allow-credentials: true - # max-age: 1800 + cors: + allowed-origins: "http://localhost:4200,https://localhost:4200" + allowed-methods: "*" + allowed-headers: "*" + exposed-headers: "Authorization,Link,X-Total-Count" + allow-credentials: true + max-age: 1800 security: clients: default: