Response for preflight does not have HTTP ok status in angular

Solution 1:

The CORS contract requires that authentication not be required on the pre-flight OPTIONS request. It looks like your back-end is requiring authentication on the OPTIONS request and the GET.

When you access your back-end with Postman, you are only sending a GET. The browser will send an OPTIONS request first (without your authentication header), and look for the response to have an "Access-Control-Allow-Origin" header that matches the origin of the page making the request.

If the response to the OPTIONS request is not a 2xx, or the header is not present, or the header value does not match the requesting page's origin, you will get the error that you are experiencing, and the GET request will not be made.

TLDR; change your back-end to not require authentication for the OPTIONS method when handling the login url.

Solution 2:

If .Net Web API project, edit web.config and remove the tag below.

<handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

Solution 3:

By default, browsers won't allow users to perform Cross-origin request.

From Angular to avoid this error, we can use the proxy configuration.

Suppose if angular ui is working on localhost:4200 and it wants to call the rest end point url, e.g: https://localhost:8443/delivery/all

The below steps will address this issue.

  1. Create a proxy.config.json file in your angular application root folder. (Where package.json file exist) Proxy does is to simply take the browser request at the same domain+port where you frontend application runs and then forwards that request to your backend API server. CORS is a browser security issue and does not apply when doing “backend to backend” communication as is the case with a proxy in between.

    The content should look as follows.

    Sample:

    {
        "/delivery/all/*": {
        "target": "https://localhost:8443",
        "secure": false,
        "logLevel": "debug",
        "changeOrigin": true
        }
    }
    

    All requests made to /delivery/all/... from within our application will be forwarded to https://localhost:8443/delivery/all/

    Note: the changeOrigin property. You will definitely have to set this to true when you’re using some virtual proxies (such as configured with Apache2) on your backend

  2. Add proxy configuration while running application. Angular supports "--proxy-config" where you can supply the proxy configuration file. If you are using the "npm start" option for testing, you have to add "--proxy-config" option as given below. It has to be added in package.json file.

     "scripts": {
    
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.config.json",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
    }
    

    If you are running directly using "ng serve" then it has be modified as given below. "ng serve --proxy-config proxy.config.json"

  3. The HTTP call inside our Angular application can be changed to this. Server will automatically forward the request to "https://localhost:8443/delivery/all".

    this.http.get('https://localhost:8443/delivery/all') .map(res => res.json());

    to

    this.http.get('/delivery/all') .map(res => res.json());

here is link for more information: https://sudhasoftjava.wordpress.com/2018/10/05/proxy-configuration-in-angular/

Solution 4:

What we've done is add a custom configuration for Cors. And then enable it through the security configuration in the java server. This Server was only enabled for direct REST calls as explained in the answer.

@Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                        .allowedHeaders("*");
            }
        };
    }
}

And this goes into the web security configuration:

@Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.csrf().disable()
                .antMatcher("/**")
                .authorizeRequests().and()
                .httpBasic()
                .and()
                .authorizeRequests().anyRequest().authenticated().and().cors();
    }