0

I hosted my frontend (react) and backend (springboot) subfolders separately on Railway. I am getting CORS error after updating the origin where the frontend is deployed as follows:

This is my configuration in spring:

@Configuration
public class DataRestConfig implements RepositoryRestConfigurer {
    private String theAllowedOrigins = "https://finance-app-frontend-production-7ab9.up.railway.app";
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
        HttpMethod[] theUnsupportedActions = {HttpMethod.PATCH};
        config.exposeIdsFor(Expense.class);
        config.exposeIdsFor(Goal.class);
        // disable HTTP methods
        disableHttpMethods(Expense.class, config, theUnsupportedActions);
        disableHttpMethods(Goal.class, config, theUnsupportedActions);

//        Configure CORS Mapping
        cors.addMapping(config.getBasePath() + "/**")
                .allowedOrigins(theAllowedOrigins).allowedMethods("GET", "POST", "DELETE", "PUT");
    }

    private void disableHttpMethods(Class theClass, RepositoryRestConfiguration config, HttpMethod[] theUnsupportedActions) {
        config.getExposureConfiguration()
                .forDomainType(theClass)
                .withItemExposure((metadata, httpMethods) -> httpMethods.disable(theUnsupportedActions))
                .withCollectionExposure((metadata, httpMethods) -> httpMethods.disable(theUnsupportedActions));
    }
}

and

package com.example.demo.config;
import com.okta.spring.boot.oauth.Okta;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;


@Configuration
public class SecurityConfiguration {


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        // Disable cross site request forgery
        http.csrf(csrf -> csrf.disable())
                .cors(cors -> {
                    cors.configurationSource(corsConfigurationSource());
                }

                )

                // Protect endpoints at /api/<type>/secure
                .authorizeHttpRequests(auth -> auth
                                .requestMatchers("/api/expenses/**").authenticated()
                                .requestMatchers("/api/goals/**").authenticated()
                )


                .oauth2ResourceServer((oauth2) -> oauth2
                        .jwt(Customizer.withDefaults())
                )

                // Add content negotiation strategy
                .setSharedObject(ContentNegotiationStrategy.class,
                        new HeaderContentNegotiationStrategy());
        Okta.configureResourceServer401ResponseBody(http);
        return http.build(); 
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("https://finance-app-frontend-production-7ab9.up.railway.app");
//        configuration.addAllowedMethod("*");
        configuration.setAllowedMethods(Arrays.asList("GET","POST", "PUT", "DELETE", "PATCH"));
        configuration.addAllowedHeader("*");
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new
                UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }


}


When I tested the APIs in postman, they worked for all APIs except for the APIs with /api/goals/** (Not sure why I get a 403 error) Below are examples of the controllers

@CrossOrigin("https://finance-app-frontend-production-7ab9.up.railway.app")
@RestController
@RequestMapping("/api/expenses")
public class ExpenseController {
    private ExpenseService expenseService;

    @Autowired
    public ExpenseController(ExpenseService expenseService) {
        this.expenseService = expenseService;
    }

    @PostMapping("/add")
    public void addExpense(@RequestHeader(value="Authorization") String token,
                           @RequestBody AddExpenseRequest addExpenseRequest) throws Exception {
        String userEmail = ExtractJWT.payloadJWTExtract(token, "\"sub\"");
        if (userEmail==null) {
            throw new Exception("User email is missing");
        }
        expenseService.addExpense(userEmail, addExpenseRequest);
    }
}

and

@CrossOrigin("https://finance-app-frontend-production-7ab9.up.railway.app")
@RestController
@RequestMapping("/api/goals")
public class GoalController {
    private GoalService goalService;

    @Autowired
    public GoalController(GoalService goalService) {
        this.goalService = goalService;
    }

    @PostMapping("/add")
    public void addGoal(@RequestHeader(value = "Authorization") String token,
                        @RequestBody AddGoalRequest addGoalRequest) throws Exception {
        String userEmail = ExtractJWT.payloadJWTExtract(token, "\"sub\"");
        if (userEmail == null) {
            throw new Exception("User email is missing");
        }
         goalService.addGoal(userEmail,addGoalRequest);
    }
}


enter image description here

Frontend: enter image description here REACT_APP_API=https://finance-app-production-8d91.up.railway.app/api (I set this variable in variables in Railway)

Appreciate my help or ideas, thanks!

6
  • I don't know much about railway, but in your browser window error it is listing multiple URLs. Is it possible it's following through some redirects and there's something in between that also needs CORs to be configured?
    – possum
    Commented Dec 24, 2023 at 8:33
  • @possum Hi, thanks for responding. Here's the full error in the console: Access to XMLHttpRequest at 'finance-app-production-8d91.up.railway.app/api/expenses/all' from origin 'finance-app-frontend-production-7ab9.up.railway.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    – Kalamazoo
    Commented Dec 24, 2023 at 11:56
  • I don't think its multiple redirect; the browser is calling the proxy URL finance-app-production-8d91.up.railway.app (not sure why there's cors error but its working fine in local).
    – Kalamazoo
    Commented Dec 24, 2023 at 11:57
  • You need to allow at least request headers Authorization and Content-Type in your CORS configuration for that client request to be accepted by the server.
    – jub0bs
    Commented Dec 24, 2023 at 14:29
  • Also: Please do not upload images of code/data/errors.
    – jub0bs
    Commented Dec 24, 2023 at 14:29

0